Ejemplo n.º 1
0
void PopAccountAdapter::GetPopAccountFromPayload(MojLogger& log, const MojObject& payload, MojObject& popAccount)
{
    MojErr err = popAccount.putString(KIND, POP_ACCOUNT_KIND);
    ErrorToException(err);

    MojObject accountId;
    err = payload.getRequired(ACCOUNT_ID, accountId);
    ErrorToException(err);
    err = popAccount.put(ACCOUNT_ID, accountId);
    ErrorToException(err);

    MojObject config;
    err = payload.getRequired(CONFIG, config);
    ErrorToException(err);

    MojObject hostname;
    err = config.getRequired(HOST_NAME, hostname);
    ErrorToException(err);
    err = popAccount.put(HOST_NAME, hostname);
    ErrorToException(err);

    MojObject port;
    err = config.getRequired(PORT, port);
    ErrorToException(err);
    err = popAccount.put(PORT, port);
    ErrorToException(err);

    MojObject encryption;
    err = config.getRequired(ENCRYPTION, encryption);
    ErrorToException(err);
    err = popAccount.put(ENCRYPTION, encryption);
    ErrorToException(err);

    MojObject username;
    err = config.getRequired(USERNAME, username);
    ErrorToException(err);
    err = popAccount.put(USERNAME, username);
    ErrorToException(err);

    // Set 'deleteFromServer' flag
    bool deleteFromServer = true;
    if (!config.get(DELETE_FROM_SERVER, deleteFromServer)) {
        // default value is true if this field doesn't exist
        deleteFromServer = true;
    }
    err = popAccount.putBool(DELETE_FROM_SERVER, deleteFromServer);
    ErrorToException(err);

    // Set 'deleteOnDevice' flag
    bool deleteOnDevice = false;
    if (!config.get(DELETE_ON_DEVICE, deleteOnDevice)) {
        // defaul value is false if this field doesn't exist
        deleteOnDevice = false;
    }
    err = popAccount.putBool(DELETE_ON_DEVICE, deleteOnDevice);
    ErrorToException(err);

    // Set sync window
    MojInt64 syncWindow;
    if (!config.get(EmailAccountAdapter::SYNC_WINDOW_DAYS, syncWindow)) {
        // set default value if this field doesn't exist
        syncWindow = PopAccount::DEFAULT_SYNC_WINDOW;
    }
    err = popAccount.putInt(EmailAccountAdapter::SYNC_WINDOW_DAYS, syncWindow);
    ErrorToException(err);

    // Set sync frequency
    MojInt64 syncFreq;
    if (!config.get(SYNC_FREQUENCY_MINS, syncFreq)) {
        syncFreq = PopAccount::DEFAULT_SYNC_FREQUENCY_MINS;
    }
    err = popAccount.putInt(SYNC_FREQUENCY_MINS, syncFreq);
    ErrorToException(err);
}
Ejemplo n.º 2
0
void SyncStateUpdater::UpdateSyncState(MojSignal<>::SlotRef slot, const SyncState& syncState, bool clearSyncState)
{
	m_doneSignal.connect(slot);

	MojErr err;
	MojObject batchPayload;
	MojObject batchOperations;

	// Delete old sync state

	MojObject delPayload;

	MojDbQuery query;

	err = query.from(SyncStateAdapter::SYNC_STATE_KIND);
	ErrorToException(err);

	MojString capabilityProvider;
	capabilityProvider.assign(m_capabilityProvider.c_str());
	err = query.where(SyncStateAdapter::CAPABILITY_PROVIDER, MojDbQuery::OpEq, capabilityProvider);
	ErrorToException(err);

	err = query.where(SyncStateAdapter::ACCOUNT_ID, MojDbQuery::OpEq, syncState.GetAccountId());
	ErrorToException(err);

	err = query.where(SyncStateAdapter::COLLECTION_ID, MojDbQuery::OpEq, syncState.GetCollectionId());
	ErrorToException(err);

	MojObject queryObj;
	err = query.toObject(queryObj);
	ErrorToException(err);

	err = delPayload.put("query", queryObj);
	ErrorToException(err);

	MojObject delOperation;
	err = delOperation.putString("method", "del");
	ErrorToException(err);
	err = delOperation.put("params", delPayload);
	ErrorToException(err);

	err = batchOperations.push(delOperation);
	ErrorToException(err);

	if(!clearSyncState) { // Store new sync state
		MojObject putPayload;

		MojObject syncStateObj;
		SyncStateAdapter::SerializeToDatabaseObject(syncState, syncStateObj, m_capabilityProvider.c_str(), m_busAddress.c_str());

		MojObject objects;
		err = objects.push(syncStateObj);
		ErrorToException(err);

		err = putPayload.put("objects", objects);
		ErrorToException(err);

		MojObject putOperation;
		err = putOperation.putString("method", "put");
		ErrorToException(err);
		err = putOperation.put("params", putPayload);
		ErrorToException(err);

		err = batchOperations.push(putOperation);
		ErrorToException(err);
	}

	err = batchPayload.put("operations", batchOperations);
	ErrorToException(err);

	// Note: batch operations are not atomic, this is just for convenience and performance
	m_busClient.SendRequest(m_updateSlot, "com.palm.tempdb", "batch", batchPayload);
}
Ejemplo n.º 3
0
void MojoDBProxy::ActivityLoadResults(MojServiceMessage *msg,
	const MojObject& response, MojErr err)
{
	LOG_TRACE("Entering function %s", __FUNCTION__);
	LOG_DEBUG("Processing Activities loaded from MojoDB");

	/* Don't allow the Activity Manager to start up if the MojoDB load
	 * fails ... */
	if (err != MojErrNone) {
		if (MojoCall::IsPermanentFailure(msg, response, err)) {
			LOG_ERROR(MSGID_LOAD_ACTIVITIES_FROM_DB_FAIL, 0,
				     "Uncorrectable error loading Activities from MojoDB: %s", MojoObjectJson(response).c_str());
#ifdef ACTIVITYMANAGER_REQUIRE_DB
			m_app->shutdown();
#else
			m_app->ready();
#endif
		} else {
			LOG_WARNING(MSGID_ACTIVITIES_LOAD_ERR, 0, "Error loading Activities from MojoDB, retrying: %s",
                                    MojoObjectJson(response).c_str());
			m_call->Call();
		}
		return;
	}

	/* Clear current call */
	m_call.reset();

	bool found;
	MojErr err2;
	MojObject results;
	found = response.get(_T("results"), results);

	if (found) {
		for (MojObject::ConstArrayIterator iter = results.arrayBegin();
			iter != results.arrayEnd(); ++iter) {
			const MojObject& rep = *iter;
			MojInt64 activityId;

			bool found;
			found = rep.get(_T("activityId"), activityId);
			if (!found) {
				LOG_WARNING(MSGID_ACTIVITYID_NOT_FOUND, 0, "activityId not found loading Activities");
					continue;
			}

			MojString id;
			MojErr err = rep.get(_T("_id"), id, found);
			if (err) {
				LOG_WARNING(MSGID_RETRIEVE_ID_FAIL, 0, "Error retrieving _id from results returned from MojoDB");
				continue;
			}

			if (!found) {
				LOG_WARNING(MSGID_ID_NOT_FOUND, 0, "_id not found loading Activities from MojoDB");
				continue;
			}

			MojInt64 rev;
			found = rep.get(_T("_rev"), rev);
			if (!found) {
				LOG_WARNING(MSGID_REV_NOT_FOUND, 0, "_rev not found loading Activities from MojoDB");
				continue;
			}

			boost::shared_ptr<MojoDBPersistToken> pt =
				boost::make_shared<MojoDBPersistToken>(id, rev);

			boost::shared_ptr<Activity> act;

			try {
				act = m_json->CreateActivity(rep, Activity::PrivateBus, true);
			} catch (const std::exception& except) {
				LOG_WARNING(MSGID_CREATE_ACTIVITY_EXCEPTION, 1, PMLOGKS("Exception",except.what()),
					  "Activity: %s", MojoObjectJson(rep).c_str());
				m_oldTokens.push_back(pt);
				continue;
			} catch (...) {
				LOG_WARNING(MSGID_UNKNOWN_EXCEPTION, 0, "Activity : %s. Unknown exception decoding encoded",
					  MojoObjectJson(rep).c_str());
				m_oldTokens.push_back(pt);
				continue;
			}

			act->SetPersistToken(pt);

			/* Attempt to register this Activity's Id and Name, in order. */

			try {
				m_am->RegisterActivityId(act);
			} catch (...) {
				LOG_ERROR(MSGID_ACTIVITY_ID_REG_FAIL, 1, PMLOGKFV("Activity","%llu", act->GetId()), "");

				/* Another Activity is already registered.  Determine which
				 * is newer, and kill the older one. */

				boost::shared_ptr<Activity> old = m_am->GetActivity(
					act->GetId());
				boost::shared_ptr<MojoDBPersistToken> oldPt =
					boost::dynamic_pointer_cast<MojoDBPersistToken,
						PersistToken>(old->GetPersistToken());

				if (pt->GetRev() > oldPt->GetRev()) {
					LOG_WARNING(MSGID_ACTIVITY_REPLACED, 4, PMLOGKFV("Activity","%llu",act->GetId()),
						    PMLOGKFV("revision","%llu",(unsigned long long)pt->GetRev()),
						    PMLOGKFV("old_Activity","%llu",old->GetId()),
						    PMLOGKFV("old_revision","%llu",(unsigned long long)oldPt->GetRev()), "");

					m_oldTokens.push_back(oldPt);
					m_am->UnregisterActivityName(old);
					m_am->ReleaseActivity(old);

					m_am->RegisterActivityId(act);
				} else {
					LOG_WARNING(MSGID_ACTIVITY_NOT_REPLACED, 4, PMLOGKFV("Activity","%llu",act->GetId()),
						    PMLOGKFV("revision","%llu",(unsigned long long)pt->GetRev()),
						    PMLOGKFV("old_Activity","%llu",old->GetId()),
						    PMLOGKFV("old_revision","%llu",(unsigned long long)oldPt->GetRev()), "");

					m_oldTokens.push_back(pt);
					m_am->ReleaseActivity(act);
					continue;
				}
			}

			try {
				m_am->RegisterActivityName(act);
			} catch (...) {
				LOG_ERROR(MSGID_ACTIVITY_NAME_REG_FAIL, 3, PMLOGKFV("Activity","%llu",act->GetId()),
					  PMLOGKS("Creator_name",act->GetCreator().GetString().c_str()),
					  PMLOGKS("Register_name",act->GetName().c_str()), "");

				/* Another Activity is already registered.  Determine which
				 * is newer, and kill the older one. */

				boost::shared_ptr<Activity> old = m_am->GetActivity(
					act->GetName(), act->GetCreator());
				boost::shared_ptr<MojoDBPersistToken> oldPt =
					boost::dynamic_pointer_cast<MojoDBPersistToken,
						PersistToken>(old->GetPersistToken());

				if (pt->GetRev() > oldPt->GetRev()) {
					LOG_WARNING(MSGID_ACTIVITY_REPLACED, 4, PMLOGKFV("Activity","%llu",act->GetId()),
						    PMLOGKFV("revision","%llu",(unsigned long long)pt->GetRev()),
						    PMLOGKFV("old_Activity","%llu",old->GetId()),
						    PMLOGKFV("old_revision","%llu",(unsigned long long)oldPt->GetRev()), "");

					m_oldTokens.push_back(oldPt);
					m_am->UnregisterActivityName(old);
					m_am->ReleaseActivity(old);

					m_am->RegisterActivityName(act);
				} else {
					LOG_WARNING(MSGID_ACTIVITY_NOT_REPLACED, 4, PMLOGKFV("Activity","%llu",act->GetId()),
						    PMLOGKFV("revision","%llu",(unsigned long long)pt->GetRev()),
						    PMLOGKFV("old_Activity","%llu",old->GetId()),
						    PMLOGKFV("old_revision","%llu",(unsigned long long)oldPt->GetRev()), "");

					m_oldTokens.push_back(pt);
					m_am->ReleaseActivity(act);
					continue;
				}
			}

			LOG_DEBUG("[Activity %llu] (\"%s\"): _id %s, rev %llu loaded",
				act->GetId(), act->GetName().c_str(), id.data(),
				(unsigned long long)rev);

			/* Request Activity be scheduled.  It won't transition to running
			 * until after the MojoDB load finishes (and the Activity Manager
			 * moves to the ready() and start()ed states). */
			m_am->StartActivity(act);
		}
	}

	MojString page;
	err2 = response.get(_T("page"), page, found);
	if (err2) {
		LOG_ERROR(MSGID_GET_PAGE_FAIL, 0, "Error getting page parameter in MojoDB query response");
		return;
	}

	if (found) {
		LOG_DEBUG("Preparing to request next page (\"%s\") of Activities",
			page.data());

		MojObject query;
		query.putString(_T("from"), ActivityKind);

		query.putString(_T("page"), page);

		MojObject params;
		params.put(_T("query"), query);

		m_call = boost::make_shared<MojoWeakPtrCall<MojoDBProxy> >(
			boost::dynamic_pointer_cast<MojoDBProxy, PersistProxy>
				(shared_from_this()),
			&MojoDBProxy::ActivityLoadResults,
			m_service, "palm://com.palm.db/find", params);

		m_call->Call();
	} else {
		LOG_DEBUG("All Activities successfully loaded from MojoDB");

		if (!m_oldTokens.empty()) {
			LOG_DEBUG("Beginning purge of old Activities from database");
			PreparePurgeCall();
			m_call->Call();
		} else {
#ifdef ACTIVITYMANAGER_CALL_CONFIGURATOR
			PrepareConfiguratorCall();
			m_call->Call();
#else
			m_call.reset();
			m_am->Enable(ActivityManager::CONFIGURATION_LOADED);
#endif
		}

		m_app->ready();
	}
}
Ejemplo n.º 4
0
void SmtpValidator::LoginSuccess()
{
	if (m_timeoutId) {
		g_source_remove(m_timeoutId);
		m_timeoutId = 0;
	}

	//MojLogInfo(m_log, "SmtpValidator %p LoginSuccess, was trying to connect to %s:%d", this, m_account->GetHostname().c_str(), m_account->GetPort());
	MojLogInfo(m_log, "SmtpValidator %p LoginSuccess", this);
	try {
		MojObject reply;
		MojErr err;

		err = reply.putBool(MojServiceMessage::ReturnValueKey, true);
		ErrorToException(err);

		if(m_account->GetEncryption() == SmtpAccount::Encrypt_TLSIfAvailable) {
			// Update protocol settings
			MojObject config;
			if(m_protocolSettings.get(SmtpAccountAdapter::CONFIG, config) && !config.null()) {
				err = config.putString(SmtpAccountAdapter::ENCRYPTION,
						m_tlsSupported ? SmtpAccountAdapter::TLS : SmtpAccountAdapter::NO_SSL);
				ErrorToException(err);

				err = m_protocolSettings.put(SmtpAccountAdapter::CONFIG, config);
				ErrorToException(err);
			}
		}

		err = reply.put("protocolSettings", m_protocolSettings);
		ErrorToException(err);

		// create credentials object
		MojObject password;
		err = password.putString("password", m_account->GetPassword().c_str());
		ErrorToException(err);
		MojObject smtp;
		err = smtp.put("smtp", password);
		ErrorToException(err);

		err = reply.put("credentials", smtp);
		ErrorToException(err);

		if (!m_replied) {
			// if we already replied due to a timeout, don't reply again.
			err = m_msg->reply(reply);
			ErrorToException(err);
			
			m_replied = true;
		}
	} catch (const exception& e) {
		if (!m_replied) {
			// if we already replied due to a timeout, don't reply again.
			m_msg->replyError(MojErrInternal);
		
			m_replied = true;
		}
	}
	
	RunState(State_SendQuitCommand);
	return;
}
Ejemplo n.º 5
0
    MojObject getProtocolOptions(MojString prpl)
    {
        MojObject result;

        PurplePluginProtocolInfo* info = getProtocolInfo(prpl.data());

        for(GList* l = info->protocol_options; l != NULL; l = l->next)
        {
            PurpleAccountOption* option = (PurpleAccountOption*)l->data;

            MojObject node;
            MojObject choices;

            node.putString("text", purple_account_option_get_text(option));

            switch(purple_account_option_get_type(option))
            {
            case PURPLE_PREF_BOOLEAN:
                node.putString("type", "bool");
                node.putBool("default_value",
                    purple_account_option_get_default_bool(option)
                    );
                break;

            case PURPLE_PREF_INT:
                node.putString("type", "int");
                node.putInt("default_value",
                    purple_account_option_get_default_int(option)
                    );
                break;

            case PURPLE_PREF_STRING:
                node.putString("type", "string");
                {
                    const char* def
                        = purple_account_option_get_default_string(option);
                    node.putString("default_value", def ? def : "");
                }
                break;

            case PURPLE_PREF_STRING_LIST:
                node.putString("type", "list");
                {
                    MojObject choices;

                    for (GList* list = purple_account_option_get_list(option);
                         list != NULL; list = list->next)
                    {
                        PurpleKeyValuePair* kvp = (PurpleKeyValuePair*)list->data;
                        // XXX: Dangerous!
                        if (kvp->key && kvp->value)
                            choices.putString((const char*)kvp->value,
                                              (const char*)kvp->key);
                    }
                    node.put("choices", choices);

                    const char* def
                        = purple_account_option_get_default_list_value(option);
                    node.putString("default_value", def ? def : "");
                }
                break;

            default:
                continue;
            };

            result.put(purple_account_option_get_setting(option), node);
        }

        return result;
    }
Ejemplo n.º 6
0
MojErr MojDbPermissionTest::checkPermissions(MojDb& db)
{
	MojDbReq reqOwner(false);
	MojErr err = reqOwner.domain(_T("com.foo"));
	MojTestErrCheck(err);
	MojDbReq reqFooBar(false);
	err = reqFooBar.domain(_T("com.foo.bar"));
	MojTestErrCheck(err);
	MojDbReq reqFooBarBad(false);
	err = reqFooBarBad.domain(_T("com.foobar"));
	MojTestErrCheck(err);
	MojDbReq reqGranted(false);
	err = reqGranted.domain("com.granted");
	MojTestErrCheck(err);
	MojDbReq reqEmpty(false);
	MojDbReq reqBad(false);
	err = reqBad.domain("com.bad");
	MojTestErrCheck(err);

	MojObject objNoId;
	err = objNoId.putString(MojDb::KindKey, _T("PermissionTest:1"));
	MojTestErrCheck(err);
	MojObject obj2NoId;
	err = obj2NoId.putString(MojDb::KindKey, _T("PermissionTest2:1"));
	MojTestErrCheck(err);

	// put new obj
	MojObject obj1 = objNoId;
	err = db.put(obj1, MojDb::FlagNone, reqOwner);
	MojTestErrCheck(err);
	MojObject obj2 = objNoId;
	err = db.put(obj2, MojDb::FlagNone, reqGranted);
	MojTestErrCheck(err);
	MojObject obj3 = objNoId;
	err = db.put(obj3, MojDb::FlagNone, reqBad);
	MojTestErrExpected(err, MojErrDbPermissionDenied);
	obj3 = objNoId;
	err = db.put(obj3, MojDb::FlagNone, reqFooBarBad);
	MojTestErrExpected(err, MojErrDbPermissionDenied);
	obj3 = objNoId;
	err = db.put(obj3, MojDb::FlagNone, reqFooBar);
	MojTestErrCheck(err);
	err = db.put(obj2NoId, MojDb::FlagNone, reqEmpty);
	MojTestErrCheck(err);
	// put existing obj
	err = obj1.put(_T("foo"), 1);
	MojTestErrCheck(err);
	err = db.put(obj1, MojDb::FlagNone, reqOwner);
	MojTestErrCheck(err);
	err = obj2.put(_T("foo"), 2);
	MojTestErrCheck(err);
	err = db.put(obj2, MojDb::FlagNone, reqGranted);
	MojTestErrCheck(err);
	err = obj2.put(_T("foo"), 3);
	MojTestErrCheck(err);
	err = db.put(obj2, MojDb::FlagNone, reqBad);
	MojTestErrExpected(err, MojErrDbPermissionDenied);

	// find
	MojDbQuery query;
	err = query.from(_T("PermissionTest:1"));
	MojTestErrCheck(err);
	MojDbCursor cursor;
	err = db.find(query, cursor, reqOwner);
	MojTestErrCheck(err);
	err = cursor.close();
	MojTestErrCheck(err);
	err = db.find(query, cursor, reqGranted);
	MojTestErrCheck(err);
	err = cursor.close();
	MojTestErrCheck(err);
	err = db.find(query, cursor, reqBad);
	MojTestErrExpected(err, MojErrDbPermissionDenied);
	err = cursor.close();
	MojTestErrCheck(err);

	// get
	MojObject id1;
	MojTestAssert(obj1.get(MojDb::IdKey, id1));
	bool found = false;
	MojObject gotten;
	err = db.get(id1, gotten, found, reqOwner);
	MojTestErrCheck(err);
	err = db.get(id1, gotten, found, reqGranted);
	MojTestErrCheck(err);
	err = db.get(id1, gotten, found, reqBad);
	MojTestErrExpected(err, MojErrDbPermissionDenied);

	// del by id
	err = db.del(id1, found, MojDb::FlagNone, reqBad);
	MojTestErrExpected(err, MojErrDbPermissionDenied);
	MojTestAssert(!found);
	err = db.del(id1, found, MojDb::FlagNone, reqOwner);
	MojTestErrCheck(err);
	MojTestAssert(found);
	MojObject id2;
	MojTestAssert(obj2.get(MojDb::IdKey, id2));
	err = db.del(id2, found, MojDb::FlagNone, reqGranted);
	MojTestErrCheck(err);
	MojTestAssert(found);

	// del query
	MojUInt32 count = 0;
	err = db.del(query, count, MojDb::FlagNone, reqOwner);
	MojTestErrCheck(err);
	err = db.del(query, count, MojDb::FlagNone, reqGranted);
	MojTestErrCheck(err);
	err = db.del(query, count, MojDb::FlagNone, reqBad);
	MojTestErrExpected(err, MojErrDbPermissionDenied);

	return MojErrNone;
}
Ejemplo n.º 7
0
MojErr MojDbTxnTest::run()
{
	MojErr err;
    MojDb db;

	err = MojDbTestEnv::run(MojDbTestDir);
	MojTestErrCheck(err);

    // open
    err = db.open(MojDbTestDir, env());
    MojTestErrCheck(err);

    // add type
    MojObject obj;
    err = obj.fromJson(MojKindStr);
    MojTestErrCheck(err);
    err = db.putKind(obj);
    MojTestErrCheck(err);

    for (int i = 0; i < 100; ++i) {
        MojObject obj;
        MojErr err = obj.putString(MojDb::KindKey, _T("Test:1"));
        MojTestErrCheck(err);
        err = obj.put(_T("foo"), (i + 25) % 100);
        MojTestErrCheck(err);
        err = obj.put(_T("bar"), i % 3);
        MojTestErrCheck(err);
        err = db.put(obj);
        MojTestErrCheck(err);
    }

    // db: x0 = (25, 0), (26, 1), (27, 2), (28, 0) .. x74 = (99,2), x75 = (0,0) .. x99 = (24,0)

    {
        MojDbQuery query;
        err = query.from(_T("Test:1"));
        MojTestErrCheck(err);
        err = query.where(_T("foo"), MojDbQuery::OpLessThan, 50);
        MojTestErrCheck(err);

        MojObject update;
        err = update.put(_T("bar"), -1);
        MojTestErrCheck(err);
        MojUInt32 count = 0;
        err = db.merge(query, update, count);
        MojTestErrCheck(err);
        MojTestAssert(count == 50);
    }

    // db: x0 = (25, -1) .. x24 = (49,-1), x25 = (50,1)i .. x74 = (99,2), x75 = (0,-1) .. x99 = (24, -1)

    // test visibility with update
    {
        MojDbReq req;
        // start transaction
        req.begin(&db, false);

        MojDbQuery query;
        err = query.from(_T("Test:1"));
        MojTestErrCheck(err);
        err = query.where(_T("bar"), MojDbQuery::OpEq, -1);
        MojTestErrCheck(err);

        MojObject update;
        err = update.put(_T("bar"), -2);
        MojTestErrCheck(err);

        MojUInt32 count = 0;
        err = db.merge(query, update, count, MojDb::FlagNone, req);
        MojTestErrCheck(err);
        MojTestAssert(count == 50);

        // txn: x0 = (25, -2) .. x24 = (49,-2), x25 = (50,1) .. x74 = (99,2), x75 = (0,-2) .. x99 = (24, -2)

        // visible within transaction
        {
            MojDbQuery query;
            err = query.from(_T("Test:1"));
            MojTestErrCheck(err);
            err = query.where(_T("bar"), MojDbQuery::OpEq, -2);
            MojTestErrCheck(err);

            MojObject update;
            err = update.put(_T("bar"), -2);
            MojTestErrCheck(err);

            MojUInt32 count = 0;
            err = db.merge(query, update, count, MojDb::FlagNone, req);
            MojTestErrCheck(err);
            MojTestAssert(count == 50);
        }


        // With BerkeleyDB parallel transaction is locked

        // invisible outside of transaction
        if (engineName().compare(_T("leveldb")) == 0)
        {
            MojDbQuery query;
            err = query.from(_T("Test:1"));
            MojTestErrCheck(err);
            err = query.where(_T("bar"), MojDbQuery::OpEq, -2);
            MojTestErrCheck(err);

            MojObject update;
            err = update.put(_T("bar"), -2);
            MojTestErrCheck(err);

            MojUInt32 count = 0;
            err = db.merge(query, update, count);
            MojTestErrCheck(err);
            MojTestAssert(count == 0);
        }
    }

    // invisible after aborted transaction
    {
        MojDbQuery query;
        err = query.from(_T("Test:1"));
        MojTestErrCheck(err);
        err = query.where(_T("bar"), MojDbQuery::OpEq, -2);
        MojTestErrCheck(err);

        MojObject update;
        err = update.put(_T("bar"), -2);
        MojTestErrCheck(err);

        MojUInt32 count = 0;
        err = db.merge(query, update, count);
        MojTestErrCheck(err);
        MojTestAssert(count == 0);
    }

    // test visibility with delete
    {
        MojDbReq req;
        // start transaction
        req.begin(&db, false);

        MojDbQuery query;
        err = query.from(_T("Test:1"));
        MojTestErrCheck(err);
        err = query.where(_T("bar"), MojDbQuery::OpEq, -1);
        MojTestErrCheck(err);

        MojUInt32 count = 0;
        err = db.del(query, count, MojDb::FlagNone, req);
        MojTestErrCheck(err);
        MojTestAssert(count == 50);

        // txn: x25 = (50,1) .. x74 = (99,2)

        // visible within transaction
        {
            MojDbQuery query;
            err = query.from(_T("Test:1"));
            MojTestErrCheck(err);
            err = query.where(_T("bar"), MojDbQuery::OpLessThan, 2);
            MojTestErrCheck(err);

            MojObject update;
            err = update.put(_T("bar"), -3);
            MojTestErrCheck(err);

            MojUInt32 count = 0;
            err = db.merge(query, update, count, MojDb::FlagNone, req);
            MojTestErrCheck(err);
            MojTestAssert(count == 33);
        }


        // With BerkeleyDB parallel transaction is locked

        // invisible outside of transaction
        if (engineName().compare(_T("leveldb")) == 0)
        {
            MojDbQuery query;
            err = query.from(_T("Test:1"));
            MojTestErrCheck(err);
            err = query.where(_T("bar"), MojDbQuery::OpLessThan, 2);
            MojTestErrCheck(err);

            MojObject update;
            err = update.put(_T("bar"), -3);
            MojTestErrCheck(err);

            MojUInt32 count = 0;
            err = db.merge(query, update, count);
            MojTestErrCheck(err);
            MojTestAssert(count == 83);
        }
    }

    // invisible after aborted transaction
    {
        MojDbQuery query;
        err = query.from(_T("Test:1"));
        MojTestErrCheck(err);
        err = query.where(_T("bar"), MojDbQuery::OpLessThan, 2);
        MojTestErrCheck(err);

        MojObject update;
        // Note that if we change bar=1 here we might get double-update when
        // record we just updated moved into records range ahead of our current
        // cursor position

        MojUInt32 count = 0;
        err = db.merge(query, update, count);
        MojTestErrCheck(err);
        MojTestAssert(count == 83);
    }

    err = db.close();
    MojTestErrCheck(err);

    return MojErrNone;
}
Ejemplo n.º 8
0
// NOTE: This should currently only be used for new emails
void EmailAdapter::SerializeToDatabaseObject(const Email& email, MojObject& obj)
{
	MojErr err;
	
	// Set the object kind
	err = obj.putString(KIND, Kind::EMAIL);
	ErrorToException(err);
	
	// FIXME object ID
	
	// Set the folder ID
	err = obj.put(FOLDER_ID, email.GetFolderId());
	ErrorToException(err);
	
	// Set flags
	MojObject flags;
	SerializeFlags(email, flags);

	err = obj.put(FLAGS, flags);
	ErrorToException(err);
	
	// The following fields only exist for a new e-mail to be added to the DB
	// If the e-mail object already exists in the DB, we shouldn't overwrite these fields
	// FIXME: Except for drafts. Maybe this logic should be moved elsewhere?
	if (true /*!obj.Exists()*/) {
		// Subject
		err = obj.putString(SUBJECT, email.GetSubject().c_str());
		ErrorToException(err);

		// Preview text
		err = obj.putString(SUMMARY, email.GetPreviewText().c_str());
		ErrorToException(err);
		
		// Timestamp in UTC milliseconds
		err = obj.put(TIMESTAMP, email.GetDateReceived());
		ErrorToException(err);
		
		// From address
		MojObject from;
		if(email.GetFrom().get()) // may not have a from address
			SerializeAddress(Address::Type::FROM, email.GetFrom(), from);
		err = obj.put(FROM, from);
		ErrorToException(err);
		
		// Reply-To address
		MojObject replyTo;
		if(email.GetReplyTo().get()) { // may not have a reply-to address
			SerializeAddress(Address::Type::REPLY_TO, email.GetReplyTo(), replyTo);
			err = obj.put(REPLY_TO, replyTo);
			ErrorToException(err);
		}

		// Recipients
		MojObject recipients;
		SerializeRecipients(Address::Type::TO, email.GetTo(), recipients);
		SerializeRecipients(Address::Type::CC, email.GetCc(), recipients);
		SerializeRecipients(Address::Type::BCC, email.GetBcc(), recipients);
		err = obj.put(RECIPIENTS, recipients);
		ErrorToException(err);
		
		// Parts
		MojObject parts;
		SerializeParts(email.GetPartList(), parts);
		err = obj.put(PARTS, parts);
		ErrorToException(err);

		// MessageId and InReplyTo
		DatabaseAdapter::PutOptionalString(obj, MESSAGE_ID, email.GetMessageId());
		DatabaseAdapter::PutOptionalString(obj, IN_REPLY_TO, email.GetInReplyTo());

		// Priority
		Email::Priority priority = email.GetPriority();
		if(priority == Email::Priority_High) {
			err = obj.putString(PRIORITY, PRIORITY_HIGH);
			ErrorToException(err);
		} else if(priority == Email::Priority_Low) {
			err = obj.putString(PRIORITY, PRIORITY_LOW);
			ErrorToException(err);
		}
	}
}
Ejemplo n.º 9
0
/**
 * Send IM Command handler.
 * callback Used by Activity Manager - gets fired from a DB watch
 *
 * parms from activity manager:
 *     {"$activity":{"activityId":1,"trigger":{"fired":true,"returnValue":true}}}
 */
MojErr IMServiceHandler::IMSendCmd(MojServiceMessage* serviceMsg, const MojObject parms)
{
	MojLogInfo(IMServiceApp::s_log, _T("IMSendCmd request received."));

	// log the parameters
	logMojObjectJsonString(_T("IMSendCmd parameters: %s"), parms);

	// if we were called by the activity manager we will get an activity id here to adopt
	// get the $activity object
	MojObject activityObj;
	MojInt64 activityId = 0;
	bool found = parms.get(_T("$activity"), activityObj);
	if (found)
		found = activityObj.get(_T("activityId"), activityId);
	if (!found) {
		MojString msg;
		msg.format(_T("IMSendCmd failed: parameter has no activityId"));
		MojLogError(IMServiceApp::s_log, "%s", msg.data());
		// send error back to caller
		serviceMsg->replyError(MojErrInvalidArg, msg);
		return MojErrInvalidArg;
	}

	// check for returnValue = false in trigger parameter
	MojObject trigger;
	bool retVal = false;
	found = activityObj.get(_T("trigger"), trigger);
	if (found)
		found = trigger.get(_T("returnValue"), retVal);
	if (!found || !retVal) {
		MojString msg;
		msg.format(_T("IMSendCmd failed: trigger does not have returnValue: true"));
		MojLogError(IMServiceApp::s_log, "%s", msg.data());
		// send error back to caller
		serviceMsg->replyError(MojErrInvalidArg, msg);
		return MojErrInvalidArg;
	}

	// create the outgoing command handler
	// This object is ref counted and will be deleted after the slot is invoked
	// Therefore we don't need to hold on to it or worry about deleting it
	MojRefCountedPtr<OutgoingIMCommandHandler> handler(new OutgoingIMCommandHandler(m_service, activityId));

	// query the DB for outgoing commands and send them
	MojErr err = handler->start();

	if (err) {
		MojString error;
		MojString msg;
		MojErrToString(err, error);
		msg.format(_T("OutgoingIMCommandHandler.start() failed: error %d - %s"), err, error.data());
		MojLogError(IMServiceApp::s_log, _T("%s"), msg.data());
		// send error back to caller
		serviceMsg->replyError(err, msg);
		return MojErrInternal;
	}


	// Reply to caller
	MojObject reply;
	reply.putString(_T("response"), _T("IMService processing command list"));
	serviceMsg->replySuccess(reply);

	return MojErrNone;
}
Ejemplo n.º 10
0
MojErr MojDbIndexTest::compoundTest()
{
	MojDbIndex index(NULL, NULL);
	MojRefCountedPtr<TestIndex> storageIndex(new TestIndex(false));
	MojAllocCheck(storageIndex.get());
	TestIndex& ti = *storageIndex;

	MojObject prop;
	MojErr err = prop.putString(MojDbIndex::NameKey, _T("foo"));
	MojTestErrCheck(err);
	err = index.addProp(prop);
	MojTestErrCheck(err);
	err = prop.putString(MojDbIndex::NameKey, _T("bar"));
	MojTestErrCheck(err);
	err = index.addProp(prop);
	MojTestErrCheck(err);
	err = prop.putString(MojDbIndex::NameKey, _T("baz"));
	MojTestErrCheck(err);
	err = index.addProp(prop);
	MojTestErrCheck(err);
	MojDbReq req;
	err = index.open(storageIndex.get(), (MojInt64) 0, req);
	MojTestErrCheck(err);

	err = put(index, 1, _T("{\"foo\":1}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 0 && ti.m_delCount == 0 && ti.m_set.size() == 0);
	err = put(index, 1, _T("{\"foo\":1,\"bar\":2}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 0 && ti.m_delCount == 0 && ti.m_set.size() == 0);
	err = put(index, 1, _T("{\"foo\":1,\"baz\":2}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 0 && ti.m_delCount == 0 && ti.m_set.size() == 0);
	err = put(index, 1, _T("{\"foo\":1,\"bar\":2,\"baz\":3}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 1 && ti.m_delCount == 0 && ti.m_set.size() == 1);
	err = assertContains(ti, 1, _T("[1,2,3]"));
	MojTestErrCheck(err);
	err = put(index, 1, _T("{\"foo\":1,\"bar\":-2,\"baz\":3}"), _T("{\"foo\":1,\"bar\":2,\"baz\":3}"));
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 2 && ti.m_delCount == 1 && ti.m_set.size() == 1);
	err = assertContains(ti, 1, _T("[1,-2,3]"));
	MojTestErrCheck(err);
	err = del(index, 1, _T("{\"foo\":1,\"bar\":-2,\"baz\":3}"));
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 2 && ti.m_delCount == 2 && ti.m_set.size() == 0);
	err = put(index, 1, _T("{\"foo\":1,\"bar\":[2,-2],\"baz\":3}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 4 && ti.m_delCount == 2 && ti.m_set.size() == 2);
	err = assertContains(ti, 1, _T("[1,2,3]"));
	MojTestErrCheck(err);
	err = assertContains(ti, 1, _T("[1,-2,3]"));
	MojTestErrCheck(err);
	err = del(index, 1, _T("{\"foo\":1,\"bar\":[2,-2],\"baz\":3}"));
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 4 && ti.m_delCount == 4 && ti.m_set.size() == 0);
	err = put(index, 1, _T("{\"foo\":1,\"bar\":[2,2,2],\"baz\":3}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 5 && ti.m_delCount == 4 && ti.m_set.size() == 1);
	err = assertContains(ti, 1, _T("[1,2,3]"));
	MojTestErrCheck(err);
	err = put(index, 1, _T("{\"foo\":1,\"bar\":[2,8],\"baz\":[3,4]}"), _T("{\"foo\":1,\"bar\":[2,2,2],\"baz\":3}"));
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 8 && ti.m_delCount == 4 && ti.m_set.size() == 4);
	err = assertContains(ti, 1, _T("[1,2,3]"));
	MojTestErrCheck(err);
	err = assertContains(ti, 1, _T("[1,2,4]"));
	MojTestErrCheck(err);
	err = assertContains(ti, 1, _T("[1,8,3]"));
	MojTestErrCheck(err);
	err = assertContains(ti, 1, _T("[1,8,4]"));
	MojTestErrCheck(err);

	err = index.close();
	MojTestErrCheck(err);

	return MojErrNone;
}
Ejemplo n.º 11
0
MojErr MojDbIndexTest::defaultValuesTest()
{
	MojDbIndex index(NULL, NULL);
	MojRefCountedPtr<TestIndex> storageIndex(new TestIndex(false));
	MojAllocCheck(storageIndex.get());
	TestIndex& ti = *storageIndex;

	MojObject prop;
	MojErr err = prop.putString(MojDbIndex::NameKey, _T("foo"));
	MojTestErrCheck(err);
	err = prop.putInt(MojDbIndex::DefaultKey, 100);
	MojTestErrCheck(err);
	err = index.addProp(prop);
	MojTestErrCheck(err);
	MojDbReq req;
	err = index.open(storageIndex.get(), (MojInt64) 0, req);
	MojTestErrCheck(err);

	err = put(index, 1, _T("{\"bar\":1}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 1 && ti.m_delCount == 0 && ti.m_set.size() == 1);
	err = put(index, 1, _T("{\"foo\":5}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 2 && ti.m_delCount == 0 && ti.m_set.size() == 2);
	err = put(index, 1, _T("{\"foo\":{\"bar\":3}}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti.m_putCount == 3 && ti.m_delCount == 0 && ti.m_set.size() == 3);

	err = index.close();
	MojTestErrCheck(err);

	MojDbIndex index2(NULL, NULL);
	MojRefCountedPtr<TestIndex> storageIndex2(new TestIndex(false));
	MojAllocCheck(storageIndex2.get());
	TestIndex& ti2 = *storageIndex2;

	MojObject prop2;
	err = prop2.putString(MojDbIndex::NameKey, _T("bar"));
	MojTestErrCheck(err);
	err = index2.addProp(prop2);
	MojTestErrCheck(err);
	err = index2.open(storageIndex2.get(), (MojInt64) 0, req);
	MojTestErrCheck(err);

	err = put(index2, 1, _T("{\"bar\":1}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti2.m_putCount == 1 && ti2.m_delCount == 0 && ti2.m_set.size() == 1);
	err = put(index2, 1, _T("{\"foo\":5}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti2.m_putCount == 1 && ti2.m_delCount == 0 && ti2.m_set.size() == 1);
	err = put(index2, 1, _T("{\"foo\":{\"bar\":3}}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti2.m_putCount == 1 && ti2.m_delCount == 0 && ti2.m_set.size() == 1);

	err = index2.close();
	MojTestErrCheck(err);

	MojDbIndex index3(NULL, NULL);
	MojRefCountedPtr<TestIndex> storageIndex3(new TestIndex(false));
	MojAllocCheck(storageIndex3.get());
	TestIndex& ti3 = *storageIndex3;

	MojObject prop3;
	err = prop3.putString(MojDbIndex::NameKey, _T("bar"));
	MojTestErrCheck(err);
	err = index3.addProp(prop3);
	MojTestErrCheck(err);
	err = prop3.putString(MojDbIndex::NameKey, _T("foo"));
	MojTestErrCheck(err);
	err = prop3.putInt(MojDbIndex::DefaultKey, 100);
	MojTestErrCheck(err);
	err = index3.addProp(prop3);
	MojTestErrCheck(err);
	err = index3.open(storageIndex3.get(), (MojInt64) 0, req);
	MojTestErrCheck(err);

	err = put(index3, 1, _T("{\"bar\":1}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti3.m_putCount == 1 && ti3.m_delCount == 0 && ti3.m_set.size() == 1);
	err = put(index3, 1, _T("{\"foo\":5}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti3.m_putCount == 1 && ti3.m_delCount == 0 && ti3.m_set.size() == 1);
	err = put(index3, 1, _T("{\"foo\":{\"bar\":3}}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti3.m_putCount == 1 && ti3.m_delCount == 0 && ti3.m_set.size() == 1);
	err = put(index3, 1, _T("{\"foo\":5, \"bar\":5}"), NULL);
	MojTestErrCheck(err);
	MojTestAssert(ti3.m_putCount == 2 && ti3.m_delCount == 0 && ti3.m_set.size() == 2);

	err = index3.close();
	MojTestErrCheck(err);

	return MojErrNone;
}
MojErr ActivityManager::InfoToJson(MojObject& rep) const
{
	MojLogTrace(s_log);

	MojErr err = MojErrNone;

	/* Scan the various run queues of the Activity Manager */
	MojObject queues(MojObject::TypeArray);

	for (int i = 0; i < RunQueueMax; i++) {
		if (!m_runQueue[i].empty()) {
			MojObject activities(MojObject::TypeArray);

			std::for_each(m_runQueue[i].begin(), m_runQueue[i].end(),
				boost::bind(&Activity::PushIdentityJson, _1,
					boost::ref(activities)));

			MojObject queue;
			err = queue.putString(_T("name"), RunQueueNames[i]);
			MojErrCheck(err);

			err = queue.put(_T("activities"), activities);
			MojErrCheck(err);

			err = queues.push(queue);
			MojErrCheck(err);
		}
	}

	if (!queues.empty()) {
		err = rep.put(_T("queues"), queues);
		MojErrCheck(err);
	}

	std::vector<boost::shared_ptr<const Activity> > leaked;

	std::set_difference(
		boost::make_transform_iterator(m_idTable.cbegin(),
			boost::bind<boost::shared_ptr<const Activity> >
				(&Activity::shared_from_this, _1)),
		boost::make_transform_iterator(m_idTable.cend(),
			boost::bind<boost::shared_ptr<const Activity> >
				(&Activity::shared_from_this, _1)),
		boost::make_transform_iterator(m_activities.begin(),
			boost::bind(&ActivityMap::value_type::second, _1)),
		boost::make_transform_iterator(m_activities.end(),
			boost::bind(&ActivityMap::value_type::second, _1)),
		std::back_inserter(leaked));

	if (!leaked.empty()) {
		MojObject leakedActivities(MojObject::TypeArray);

		std::for_each(leaked.begin(), leaked.end(),
			boost::bind(&Activity::PushIdentityJson, _1,
				boost::ref(leakedActivities)));

		err = rep.put(_T("leakedActivities"), leakedActivities);
		MojErrCheck(err);
	}

	return MojErrNone;
}
Ejemplo n.º 13
0
MojErr MojDbKind::configureIndexes(const MojObject& obj, const MojString& locale, MojDbReq& req)
{
	MojLogTrace(s_log);

	// make sure indexes changes count against our usage
	MojErr err = req.curKind(this);
	MojErrCheck(err);

	// add default id index to set
	MojObject idIndex;
	err = idIndex.fromJson(IdIndexJson);
	MojErrCheck(err);
	ObjectSet newIndexObjects;
	err = newIndexObjects.put(idIndex);
	MojErrCheck(err);
	// change back to a set and use contains
	MojSet<MojString> indexNames;
	MojString defaultIdxName;
	err = defaultIdxName.assign(IdIndexName);
	MojErrCheck(err);
	err = indexNames.put(defaultIdxName);
	MojErrCheck(err);
	// add indexes to set to uniquify and order them
	MojObject indexArray;
	if (obj.get(IndexesKey, indexArray)) {
		MojObject::ConstArrayIterator end = indexArray.arrayEnd();
		for (MojObject::ConstArrayIterator i = indexArray.arrayBegin(); i != end; ++i) {
			MojString indexName;
			err = i->getRequired(MojDbIndex::NameKey, indexName);
			MojErrCheck(err);
			err = indexName.toLower();
			MojErrCheck(err);
			if (!indexNames.contains(indexName)) {
				MojObject idx = *i;
				// make sure we keep the lower-cased index name
				err = idx.putString(MojDbIndex::NameKey, indexName);
				MojErrCheck(err);
				err = newIndexObjects.put(idx);
				MojErrCheck(err);
				err = indexNames.put(indexName);
				MojErrCheck(err);
			} else {
				MojErrThrowMsg(MojErrDbInvalidIndexName, _T("db: cannot repeat index name: '%s'"), indexName.data());
			}
		}
	}
	// figure out what to add and what to delete
	ObjectSet toDrop;
	err = m_indexObjects.diff(newIndexObjects, toDrop);
	MojErrCheck(err);
	ObjectSet toAdd;
	err = newIndexObjects.diff(m_indexObjects, toAdd);
	MojErrCheck(err);
	// drop deleted indexes
	IndexVec newIndexes;
	for (IndexVec::ConstIterator i = m_indexes.begin(); i != m_indexes.end(); ++i) {
		if (toDrop.contains((*i)->object())) {
			err = dropIndex(i->get(), req);
			MojErrCheck(err);
		} else {
			err = newIndexes.push(*i);
			MojErrCheck(err);
		}
	}
	// add new indexes
	for (ObjectSet::ConstIterator i = toAdd.begin(); i != toAdd.end(); ++i) {
		// create index
		MojRefCountedPtr<MojDbIndex> index(new MojDbIndex(this, m_kindEngine));
		MojAllocCheck(index.get());
		err = index->fromObject(*i, locale);
		MojErrCheck(err);
		// open index
		err = openIndex(index.get(), req);
		MojErrCheck(err);
		err = newIndexes.push(index);
		MojErrCheck(err);
	}
	// sort indexes by the prop vec so that for indexes that share prop prefixes, the shortest one comes first
	err = newIndexes.sort();
	MojErrCheck(err);
	// update members
	m_indexObjects = newIndexObjects;
	m_indexes = newIndexes;

	return MojErrNone;
}
Ejemplo n.º 14
0
MojErr MojDb::purge(MojUInt32& countOut, MojInt64 numDays, MojDbReqRef req)
{
	MojLogTrace(s_log);

	countOut = 0;
	if (numDays <= -1) {
		numDays = m_purgeWindow;
	}

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

	MojLogDebug(s_log, _T("purging objects deleted more than %lld days ago..."), numDays);

	MojTime time;
	err = MojGetCurrentTime(time);
	MojErrCheck(err);

	// store the revision number to current timestamp mapping
	MojObject revTimeMapping;
	MojInt64 rev;
	err = nextId(rev);
	MojErrCheck(err);
	err = revTimeMapping.put(RevNumKey, rev);
	MojErrCheck(err);
	err = revTimeMapping.put(TimestampKey, time.microsecs());
	MojErrCheck(err);
	err = revTimeMapping.putString(KindKey, MojDbKindEngine::RevTimestampId);
	MojErrCheck(err);

	err = putImpl(revTimeMapping, MojDb::FlagNone, req);
	MojErrCheck(err);

	// find the revision number for numDays prior to now
	MojInt64 purgeTime = time.microsecs() - (MojTime::UnitsPerDay * numDays);
	MojDbQuery query;
	err = query.from(MojDbKindEngine::RevTimestampId);
	MojErrCheck(err);
	query.limit(1);
	err = query.where(TimestampKey, MojDbQuery::OpLessThanEq, purgeTime);
	MojErrCheck(err);
	err = query.order(TimestampKey);
	MojErrCheck(err);
	query.desc(true);

	MojDbCursor cursor;
	err = findImpl(query, cursor, NULL, req, OpDelete);
	MojErrCheck(err);
	bool found = false;
	MojObject obj;
	err = cursor.get(obj, found);
	MojErrCheck(err);
	err = cursor.close();
	MojErrCheck(err);

	MojUInt32 batchCount = 0;
	MojUInt32 totalCount = 0;

	while ((found))
	{
		// Do it in AutoBatchSize batches
		batchCount = 0;
		req->fixmode(true);		// purge even if index mis-matches
		err = purgeImpl(obj, batchCount, req);
		MojLogDebug(s_log, _T("purge batch processed: batch: %d; total: %d; err = %d\n"),
					batchCount, (totalCount + batchCount), err);
		MojErrCheck(err);
		totalCount += batchCount;
		countOut = totalCount;
		if (batchCount < AutoBatchSize)	// last batch
			break;
		err = commitBatch(req);
		MojErrCheck(err);
		continue;
	}

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

	MojLogDebug(s_log, _T("purged %d objects"), countOut);


	return MojErrNone;
}
Ejemplo n.º 15
0
void PopAccountAdapter::SerializeToDatabasePopObject(const PopAccount& accnt, MojObject& obj)
{
    MojErr err;
    // Set the object kind
    err = obj.putString(KIND, POP_ACCOUNT_KIND);
    ErrorToException(err);

    // Set ID
    err = obj.put(ID, accnt.GetId());
    ErrorToException(err);

    // Set account ID
    err = obj.put(ACCOUNT_ID, accnt.GetAccountId());
    ErrorToException(err);

    // Set host name
    err = obj.putString(HOST_NAME, accnt.GetHostName().c_str());
    ErrorToException(err);

    // Set port
    err = obj.putInt(PORT, accnt.GetPort());
    ErrorToException(err);

    // Set encryption
    err = obj.putString(ENCRYPTION, accnt.GetEncryption().c_str());
    ErrorToException(err);

    // Set user name
    err = obj.putString(USERNAME, accnt.GetUsername().c_str());
    ErrorToException(err);

    // Set 'initialSynced' flag
    err = obj.putBool(INITIAL_SYNC, accnt.IsInitialSync());
    ErrorToException(err);

    // Set 'deleteFromServer' flag
    err = obj.putBool(DELETE_FROM_SERVER, accnt.IsDeleteFromServer());
    ErrorToException(err);

    // Set 'deleteOnDevice' flag
    err = obj.putBool(DELETE_ON_DEVICE, accnt.IsDeleteOnDevice());
    ErrorToException(err);

    // Set sync window
    err = obj.putInt(EmailAccountAdapter::SYNC_WINDOW_DAYS, accnt.GetSyncWindowDays());
    ErrorToException(err);

    // Set sync frequency
    err = obj.putInt(SYNC_FREQUENCY_MINS, accnt.GetSyncFrequencyMins());
    ErrorToException(err);

    if (accnt.IsError()) {
        MojObject mojErr;
        err = mojErr.putInt(EmailAccountAdapter::ERROR_CODE, (int)accnt.GetError().errorCode);
        ErrorToException(err);

        err = mojErr.putString(EmailAccountAdapter::ERROR_TEXT, accnt.GetError().errorText.c_str());
        ErrorToException(err);

        err = obj.put(EmailAccountAdapter::ERROR, mojErr);
        ErrorToException(err);
    } else {
        err = obj.put(EmailAccountAdapter::ERROR, MojObject::Null);
    }

    SerializeSpecialFolders(accnt, obj);
}
/**
 * Callback from the save buddy in buddyStatus DB call.
 *
 * Now save in contacts db
 */
MojErr SendOneCommandHandler::addBuddyResult(MojObject& result, MojErr saveErr)
{
	MojLogTrace(IMServiceApp::s_log);

	if (saveErr) {
		MojString error;
		MojErrToString(saveErr, error);
		MojLogError(IMServiceApp::s_log, _T("addBuddyResult failed. error %d - %s"), saveErr, error.data());
	}
	else {
		IMServiceHandler::logMojObjectJsonString(_T("addBuddyResult success: %s"), result);
	}

	// now add to contacts DB
	// create the DB object
	//{
	//    accountId:<>,
	//    displayName:<>,
	//    photos:[{localFilepath:<>}],
	//    ims:[{value:<>, type:<>}]
	// }
	MojObject contact;
	contact.putString("_kind", IM_CONTACT_KIND);
	contact.put("accountId", m_accountId);
	contact.put("remoteId", m_buddyName); // using username as remote ID since we don't have anything else and this should be unique

	// "ims" array
	MojObject newImsArray, newImObj;
	newImObj.put("value", m_buddyName);
	newImObj.put("type", m_serviceName);
	// Note we need this twice since some services look for "serviceName" and some look for "type"... Maybe we can evenutally standardize...
	newImObj.put("serviceName", m_serviceName);
	newImsArray.push(newImObj);
	contact.put("ims", newImsArray);

	// need to add email address too for contacts linker
	//    email:[{value:<>}]
	MojString emailAddr;
	bool validEmail = true;
	emailAddr.assign(m_buddyName.data());
	// for AIM, need to add back the "@aol.com" to the email
	if (MojInvalidIndex == m_buddyName.find('@')) {
		if (0 == m_serviceName.compare(SERVICENAME_AIM))
			emailAddr.append("@aol.com");
		else
			validEmail = false;
	}

	if (validEmail) {
		MojObject newEmailArray, newEmailObj;
		newEmailObj.put("value", emailAddr);
		newEmailArray.push(newEmailObj);
		contact.put("emails", newEmailArray);
	}

	// log it
	MojString json;
	contact.toJson(json);
	MojLogInfo(IMServiceApp::s_log, _T("saving contact to db: %s"), json.data());

	// save it
	// the save generates a call to the save result handler
	MojErr err = m_dbClient.put(this->m_addContactSlot, contact);
	if (err) {
		MojString error;
		MojErrToString(err, error);
		MojLogError(IMServiceApp::s_log, _T("addBuddyResult: dbClient.put() failed: error %d - %s"), err, error.data());
		// tell the outgoing Command handler we are done
		m_outgoingIMHandler->messageFinished();
	}

	return MojErrNone;
}
Ejemplo n.º 17
0
MojErr MojDbPerfUpdateTest::updateObjsViaMerge(MojDb& db, const MojChar* kindId, MojErr (MojDbPerfTest::*createFn) (MojObject&, MojUInt64))
{
	// register all the kinds
	MojTime time;
	MojErr err = putKinds(db, time);
	MojTestErrCheck(err);

	// put objects using createFn
	MojObject objs;
	err = putObjs(db, kindId, numInsertForPut, createFn, objs);
	MojTestErrCheck(err);

	MojObject midObj;
	bool found = objs.at(numInsertForPut/2, midObj);
	MojTestAssert(found);

	MojTime objTime;
	err = mergeObj(db, midObj, objTime);
	MojTestErrCheck(err);
	MojUInt64 mergeTime = objTime.microsecs();
	err = MojPrintF("\n -------------------- \n");
	MojTestErrCheck(err);
	err = MojPrintF("   merging single object - index %llu - of kind %s %llu times took: %llu microsecs\n", numInsertForPut/2, kindId, numMergeIterations, mergeTime);
	MojTestErrCheck(err);
	err = MojPrintF("   time per merge: %llu microsecs", (mergeTime) / (numMergeIterations));
	MojTestErrCheck(err);
	err = MojPrintF("\n\n");
	MojTestErrCheck(err);

	MojString buf;
	err = buf.format("Merge single object - index %llu - %llu times,%s,%llu,%llu,%llu,\n", numInsertForPut/2, numMergeIterations, kindId, mergeTime, mergeTime/numMergeIterations, mergeTime/(1*numMergeIterations));
	MojTestErrCheck(err);
	err = fileWrite(file, buf);
	MojTestErrCheck(err);

	MojTime batchTime;
	MojObject::ArrayIterator beginArr;
	err = objs.arrayBegin(beginArr);
	MojErrCheck(err);
	err = batchMergeObj(db, beginArr, beginArr + (numInsertForPut / 10), batchTime);
	MojTestErrCheck(err);
	mergeTime = batchTime.microsecs();
	err = MojPrintF("   merging batch - %llu objects - of kind %s %llu times took: %llu microsecs\n", numInsertForPut/10, kindId, numBatchMergeIterations, mergeTime);
	MojTestErrCheck(err);
	err = MojPrintF("   time per batch merge: %llu microsecs\n", (mergeTime) / (numBatchMergeIterations));
	MojTestErrCheck(err);
	err = MojPrintF("   time per object: %llu microsecs", (mergeTime) / (numInsertForPut/10 * numBatchMergeIterations));
	MojTestErrCheck(err);
	err = MojPrintF("\n\n");
	MojTestErrCheck(err);

	err = buf.format("Batch merge %llu objects %llu times,%s,%llu,%llu,%llu,\n", numInsertForPut/10, numBatchMergeIterations, kindId, mergeTime, mergeTime/numBatchMergeIterations, mergeTime/(numInsertForPut/10*numBatchMergeIterations));
	MojTestErrCheck(err);
	err = fileWrite(file, buf);
	MojTestErrCheck(err);

	MojTime mergeQueryTime;
	MojTestErrCheck(err);
	MojDbQuery query;
	err = query.from(kindId);
	MojTestErrCheck(err);
	query.limit(numInsertForPut/5);
	query.desc(true);

	MojObject queryObj;
	err = query.toObject(queryObj);
	MojTestErrCheck(err);
	MojString queryStr;
	err = queryObj.stringValue(queryStr);
	MojTestErrCheck(err);

	MojObject props;
	err = props.putString(_T("newKey"), _T("here's a new value"));
	MojTestErrCheck(err);
	MojUInt32 count;
	err = queryMergeObj(db, query, props, count, mergeQueryTime);
	MojTestErrCheck(err);
	mergeTime = mergeQueryTime.microsecs();
	err = MojPrintF("   merging with query - %d objects - of kind %s %llu times took: %llu microsecs\n", count, kindId, numBatchMergeIterations, mergeTime);
	MojTestErrCheck(err);
	err = MojPrintF("   time per merge: %llu microsecs\n", (mergeTime) / (numBatchMergeIterations));
	MojTestErrCheck(err);
	err = MojPrintF("   time per object: %llu microsecs", (mergeTime) / (count * numBatchMergeIterations));
	MojTestErrCheck(err);
	err = MojPrintF("\n\n");
	MojTestErrCheck(err);

	err = buf.format("Merge with query %s,,,,,\nMerge with query - %d objects - %llu times,%s,%llu,%llu,%llu,\n", queryStr.data(), count, numBatchMergeIterations, kindId, mergeTime, mergeTime/numBatchMergeIterations, mergeTime/(count*numBatchMergeIterations));
	MojTestErrCheck(err);
	err = fileWrite(file, buf);
	MojTestErrCheck(err);

	return MojErrNone;
}
/*
 * Send one IMCommand that has handler set to transport
 *
 * errors returned up to OutgoingIMCommandHandler
 *
 *
 * @param imCmd - imCommand that was read out of the DB with handler set to transport
 {
   "id"      : "ImCommand",
   "type"    : "object",
   "properties" : {
      "command"       : {"type"        : "string",
                         "enum"        : ["blockBuddy","deleteBuddy","sendBuddyInvite","receivedBuddyInvite","createChatGroup","inviteToGroup","leaveGroup"],
                         "description" : "The command to be processed"},
      "params"        : {"type"        : "any",
                         "description" : "Parameters associated with the command are stored here."}
      "handler"       : {"type"        : "string",
                         "enum"        : ["transport","application"],
                         "description" : "Who is responsible for handling the command"},
      "targetUsername"  : {"type"        : "string",
                         "description" : "The buddyname the command will act on"},
      "fromUsername"  : {"type"        : "string",
                         "description" : "The username that originated the command"},
      "serviceName"   : {"type"        : "string",
                         "description" : "Name of originating service (see IMAddress of contacts load library*)."}
      }
 * }
 */
MojErr SendOneCommandHandler::doSend(const MojObject imCmd) {

	IMServiceHandler::logMojObjectJsonString(_T("send command: %s"),imCmd);
	MojString command;
	LibpurpleAdapter::SendResult retVal = LibpurpleAdapter::SENT;
	bool found = false;

	MojErr err = imCmd.get(MOJDB_COMMAND, command, found);
	MojErrCheck(err);

	// serviceName
	err = imCmd.get(MOJDB_SERVICE_NAME, m_serviceName, found);
	MojErrCheck(err);

	// get the id so we can update the status in  the DB after sending
	err = imCmd.getRequired(MOJDB_ID, m_currentCmdDbId);
	MojErrCheck(err);

	// for receiving invite, the user account and remote user are reversed: targetUsername is us and the fromUsername is the remote buddy
	if (0 == command.compare(_T("receivedBuddyInvite"))) {
		// username of current account
		err = imCmd.get(MOJDB_FROM_USER, m_buddyName, found);
		MojErrCheck(err);

		// buddy / remote user
		err = imCmd.get(MOJODB_TARGET_USER, m_username, found);
		MojErrCheck(err);
	}
	else {
		// username of current account
		err = imCmd.get(MOJDB_FROM_USER, m_username, found);
		MojErrCheck(err);

		// buddy / remote user
		err = imCmd.get(MOJODB_TARGET_USER, m_buddyName, found);
		MojErrCheck(err);
	}

	// which command?
	if (0 == command.compare(_T("blockBuddy"))) {
		retVal = blockBuddy(imCmd);
	}
	else if (0 == command.compare(_T("deleteBuddy"))) {
		retVal = removeBuddy(imCmd);
	}
	else if (0 == command.compare(_T("sendBuddyInvite"))) {
		retVal = inviteBuddy(imCmd);
	}
	else if (0 == command.compare(_T("receivedBuddyInvite"))) {
		retVal = receivedBuddyInvite(imCmd);
	}
	else {
		MojLogError(IMServiceApp::s_log, _T("doSend: unknown command %s"), command.data());
		retVal = LibpurpleAdapter::SEND_FAILED;
	}

	// we can't just delete the command if the user is not logged on...
	// need to save command in "waiting" state waiting for user to login
	if (LibpurpleAdapter::USER_NOT_LOGGED_IN == retVal) {
		// user not logged in - put in queued state
		MojLogError(IMServiceApp::s_log, _T("doSend - can't process command - user not logged in. Waiting for connection"));
		MojObject propObject;
		propObject.putString(MOJDB_STATUS, IMMessage::statusStrings[WaitingForConnection]);

		// id to update
		propObject.putString(MOJDB_ID, m_currentCmdDbId);

		// save the new fields - call merge
		err = m_dbClient.merge(this->m_imSaveCommandSlot, propObject);
		if (err) {
			MojLogError(IMServiceApp::s_log, _T("doSend - DB merge command failed. err %d, DB id %s: "), err, m_currentCmdDbId.data() );
		}
	}
	else {
		// delete command so we don't keep processing it
		// put id in an array
		MojObject idsToDelete;  // array
		err = idsToDelete.push(m_currentCmdDbId);

		// luna://com.palm.db/del '{"ids":[2]}'
		IMServiceHandler::logMojObjectJsonString(_T("deleting imcommand: %s"), idsToDelete);
		err = m_dbClient.del(this->m_imDeleteCommandSlot, idsToDelete.arrayBegin(), idsToDelete.arrayEnd());

		if (err) {
			MojLogError(IMServiceApp::s_log, _T("doSend - DB del command failed. err %d, DB id %s: "), err, m_currentCmdDbId.data() );
		}
	}

	if (LibpurpleAdapter::SENT != retVal) {
		// something went wrong - nothing more we can do
		MojLogError(IMServiceApp::s_log, _T("doSend: command failed"));
		m_outgoingIMHandler->messageFinished();

	}

	return MojErrNone;
}
MojErr OnEnabledHandler::findImLoginStateResult(MojObject& payload, MojErr err)
{
	MojLogTrace(IMServiceApp::s_log);

	if (err != MojErrNone) {
		MojString error;
		MojErrToString(err, error);
		MojLogCritical(IMServiceApp::s_log, _T("findImLoginStateResult failed: error %d - %s"), err, error.data());
	}
	else {
		// "results" in result
		MojObject results;
		payload.get(_T("results"), results);

		// check to see if array is empty - normally it will be if this is a newly created account. There should never be more than 1 item here
		if (!results.empty()){

			IMServiceHandler::logMojObjectJsonString(_T("findImLoginStateResult found existing imLoginState record: %s"), payload);

			// if there is a record already, make sure the account id matches.
			MojObject loginState;
			MojObject::ConstArrayIterator itr = results.arrayBegin();
			bool foundOne = false;
			while (itr != results.arrayEnd()) {
				if (foundOne) {
					MojLogError(IMServiceApp::s_log,
							_T("findImLoginStateResult: found more than one ImLoginState with same username/serviceName - using the first one"));
					break;
				}
				loginState = *itr;
				foundOne = true;
				itr++;
			}

			MojString accountId;
			MojErr err = loginState.getRequired("accountId", accountId);
			if (err) {
				MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: missing accountId in loginState entry"));
			}
			if (0 != accountId.compare(m_accountId)) {
				MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: existing loginState record does not have matching account id. accountId = %s"), accountId.data());

				// delete this record
				MojObject idsToDelete;
				MojString dbId;
				err = loginState.getRequired("_id", dbId);
				if (err) {
					MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: missing dbId in loginState entry"));
				}
				else {
				    idsToDelete.push(dbId);

					// luna://com.palm.db/del '{"ids":[2]}'
					MojLogInfo(IMServiceApp::s_log, _T("findImLoginStateResult: deleting loginState entry id: %s"), dbId.data());
					err = m_dbClient.del(this->m_deleteImLoginStateSlot, idsToDelete.arrayBegin(), idsToDelete.arrayEnd());
					if (err != MojErrNone) {
						MojString error;
						MojErrToString(err, error);
						MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: db.del() failed: error %d - %s"), err, error.data());
					}
				}
			}
			// if the account id matches, leave the old record and we are done
			else return MojErrNone;
		}

		// no existing record found or the old one was deleted - create a new one
		MojLogInfo(IMServiceApp::s_log, _T("findImLoginStateResult: no matching loginState record found for %s, %s. creating a new one"), m_username.data(), m_serviceName.data());
		MojObject imLoginState;
		imLoginState.putString(_T("_kind"), IM_LOGINSTATE_KIND);
		imLoginState.put(_T("accountId"), m_accountId);
		imLoginState.put(_T("serviceName"), m_serviceName);
		imLoginState.put(_T("username"), m_username);
        imLoginState.put(_T("capabilityId"), m_capabilityProviderId);
		imLoginState.putString(_T("state"), LOGIN_STATE_OFFLINE);
		imLoginState.putInt(_T("availability"), PalmAvailability::ONLINE); //default to online so we automatically login at first
        imLoginState.put(_T("config"), m_config);
		MojErr err = m_dbClient.put(m_addImLoginStateSlot, imLoginState);
		if (err != MojErrNone) {
			MojString error;
			MojErrToString(err, error);
			MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: db.put() failed: error %d - %s"), err, error.data());
		}

	}
	return err;
}
Ejemplo n.º 20
0
// test operator is active properly (through create / find / update / delete operation)
MojErr MojDbSearchCacheTest::operatorTest(MojDb& db)
{
    MojDbSearchCache* cache  = new MojDbSearchCache();
    MojDbSearchCache::QueryKey key1, key2, key3, key4;
    MojObject queryObj;
    MojDbQuery query, query1, query2;
    MojErr err;
    MojUInt32 rev = 0;
    MojDbSearchCache::IdSet ids1, ids2;

    MojObject id;
    err = id.putString(_T("_id"), _T("id1"));
    MojTestErrCheck(err);
    err = ids1.push(id);
    MojTestErrCheck(err);
    err = ids2.push(id);
    MojTestErrCheck(err);

    err = query.from(_T("test.cache:1"));
    MojTestErrCheck(err);
    err = query.where(_T("attr1"), MojDbQuery::OpGreaterThan, 2);
    MojTestErrCheck(err);

    key1.setRev(rev);
    key1.setQuery(query);

    key2.setRev(rev);
    key2.setQuery(query);

    err = cache->createCache(key1, ids1);
    MojTestErrCheck(err);
    err = cache->createCache(key2, ids2);
    MojTestErrCheck(err);

    /*** :: For debug ::
    for(MojDbSearchCache::Container::const_iterator i = cache->container().begin(); i != cache->container().end(); ++i) {
        MojString str1, str2;
        MojObject obj;
        MojUInt32 rev = i->first.getRev();
        str1 = i->first.getQuery();
        for(MojDbSearchCache::IdSet::ConstIterator it = i->second.begin(); it != i->second.end(); ++it) {
            err = it->toJson(str2);
            MojTestErrCheck(err);
        }

        printf("key(rev, query) : (%d, %s), ids : %s\n", rev, str1.data(), str2.data());
    }
    ***/

    MojTestAssert(cache->container().count(key1) == 1);
    MojTestAssert(cache->container().size() == 1);
    MojTestAssert(cache->contain(key1) == true);

    // nothing to update -> no-op
    err = cache->updateCache(key1, ids1);
    MojTestErrCheck(err);
    MojTestAssert(cache->container().count(key1) == 1);
    MojTestAssert(cache->container().size() == 1);
    MojTestAssert(cache->contain(key1) == true);

    err = query1.from(_T("test.cache:1"));
    MojTestErrCheck(err);
    err = query1.where(_T("attr2"), MojDbQuery::OpGreaterThan, _T(6));
    MojTestErrCheck(err);
    key3.setRev(rev);
    key3.setQuery(query1);

    // key is changed, but kind is same --> update cache
    err = cache->updateCache(key3, ids1);
    MojTestAssert(cache->container().count(key3) == 1);
    MojTestAssert(cache->container().size() == 1);
    MojTestAssert(cache->contain(key3) == true);

    err = query2.from(_T("test.update:1"));
    MojTestErrCheck(err);
    err = query2.where(_T("attr2"), MojDbQuery::OpGreaterThan, _T(6));
    MojTestErrCheck(err);
    rev = 5;
    key4.setRev(rev);
    key4.setQuery(query2);

    // key is changed -> update cache(add new cache because it is owned by different kind)
    err = cache->updateCache(key4, ids1);
    MojTestErrCheck(err);
    MojTestAssert(cache->container().count(key4) == 1);
    MojTestAssert(cache->container().size() == 2);
    MojTestAssert(cache->contain(key4) == true);

    //delete the cache added
    err = cache->destroyCache(key4);
    MojTestErrCheck(err);
    MojTestAssert(cache->container().count(key4) == 0);
    MojTestAssert(cache->container().size() == 1);
    MojTestAssert(cache->contain(key4) == false);

    return MojErrNone;
}