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); }
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); }
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(); } }
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; }
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; }
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; }
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; }
// 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); } } }
/** * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
// 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; }