void PersistCommand::Validate(bool checkTokenValid) const { LOG_AM_TRACE("Entering function %s", __FUNCTION__); if (!m_activity->IsPersistTokenSet()) { LOG_AM_ERROR(MSGID_PERSIST_TOKEN_NOT_SET,2, PMLOGKFV("activity","%llu",m_activity->GetId()), PMLOGKS("persist_command",GetString().c_str()), "Persist token for Activity is not set"); throw std::runtime_error("Persist token for Activity is not set"); } if (checkTokenValid) { boost::shared_ptr<PersistToken> pt = m_activity->GetPersistToken(); if (!pt->IsValid()) { LOG_AM_ERROR(MSGID_PERSIST_TOKEN_INVALID, 2, PMLOGKFV("activity","%llu",m_activity->GetId()), PMLOGKS("persist_command",GetString().c_str()), "Persist token for Activity is set but not valid" ); throw std::runtime_error("Persist token for Activity is set " "but not valid"); } } }
ConversionResultFlags jdouble_to_i32(double value, int32_t *result) { CHECK_POINTER_RETURN_VALUE(result, CONV_BAD_ARGS); if (isnan(value) != 0) { PJ_LOG_WARN("PBNJSON_NAN_TO_INT_WARN", 0, "attempting to convert nan to int"); *result = 0; return CONV_NOT_A_NUM; } switch (isinf(value)) { case 0: break; case 1: PJ_LOG_WARN("PBNJSON_+INF_TO_INT_WARN", 0, "attempting to convert +infinity to int"); *result = PJSON_MAX_INT; return CONV_POSITIVE_INFINITY; case -1: PJ_LOG_WARN("PBNJSON_-INF_TO_INT_WARN", 0, "attempting to convert -infinity to int"); *result = PJSON_MIN_INT; return CONV_NEGATIVE_INFINITY; default: PJ_LOG_ERR("PBNJSON_ISINF_ERR", 1, PMLOGKFV("VALUE", "%lf", value), "unknown result from isinf for %lf", value); return CONV_GENERIC_ERROR; } if (value > PJSON_MAX_INT) { PJ_LOG_WARN("PBNJSON_DBL_OO_INT_RANGE", 1, PMLOGKFV("VALUE", "%lf", value), "attempting to convert double %lf outside of int range", value); *result = PJSON_MAX_INT; return CONV_POSITIVE_OVERFLOW; } if (value < PJSON_MIN_INT) { PJ_LOG_WARN("PBNJSON_DBL_OO_INT_RANGE", 1, PMLOGKFV("VALUE", "%lf", value), "attempting to convert double %lf outside of int range", value); *result = PJSON_MIN_INT; return CONV_NEGATIVE_OVERFLOW; } #if 0 // unnecessary for 32-bits because they will always fit in a double // with no precision loss if (value > PJSON_MAX_INT_IN_DBL || value < PJSON_MIN_INT_IN_DBL) { PJ_LOG_WARN("PBNJSON_DBL_TO_INT_CONV_WARN", 1, PMLOGKFV("VALUE", "%lf", value), "conversion of double %lf to integer potentially has precision loss", value); *result = (int64_t)value; return CONV_PRECISION_LOSS; } #endif *result = (int32_t) value; if (*result != value) { PJ_LOG_WARN("PBNJSON_DBL_TO_INT_CONV_LOSS", 1, PMLOGKFV("VALUE", "%lf", value), "conversion of double %lf results in integer with different value", value); return CONV_PRECISION_LOSS; } return CONV_OK; }
void PersistCommand::Complete(bool success) { LOG_AM_TRACE("Entering function %s", __FUNCTION__); /* All steps of Complete must execute, including launching the next * command in the chain. All exceptions must be handled locally. */ try { m_completion->Complete(success); } catch (const std::exception& except) { LOG_AM_WARNING(MSGID_CMD_COMPLETE_EXCEPTION,3, PMLOGKFV("activity","%llu",m_activity->GetId()), PMLOGKS("persist_command",GetString().c_str()), PMLOGKS("exception",except.what()),"Unexpected exception while trying to complete"); } catch (...) { LOG_AM_WARNING(MSGID_CMD_COMPLETE_EXCEPTION,2, PMLOGKFV("activity","%llu",m_activity->GetId()), PMLOGKS("persist_command",GetString().c_str()),"exception while trying to complete"); } /* Tricky order here. Unhooking this command will probably destroy it, * so we have to pick up a local reference to the next command in the * chain because we won't be able to access the object property. * * The whole chain shouldn't collapse, though, as the next executing * command should be referenced by the same Activity or some other one. * It's just the reference that's bad... but since something like: * Complete "foo"/Create(and replace) "foo"/Cancel old "foo". If the * Complete is still in process, the Cancel will chain (and ultimately * will succeed as the Activity is already cancelled). */ boost::shared_ptr<PersistCommand> next = m_next; try { m_activity->UnhookPersistCommand(shared_from_this()); } catch (const std::exception& except) { LOG_AM_WARNING( MSGID_CMD_UNHOOK_EXCEPTION,3, PMLOGKFV("activity","%llu",m_activity->GetId()), PMLOGKS("persist_command",GetString().c_str()), PMLOGKS("exception",except.what()),"Unexpected exception unhooking command" ); } catch (...) { LOG_AM_WARNING(MSGID_CMD_UNHOOK_EXCEPTION,2, PMLOGKFV("activity","%llu",m_activity->GetId()), PMLOGKS("persist_command",GetString().c_str()),"exception unhooking command"); } if (next) { next->Persist(); } }
void PowerdPowerActivity::PowerUnlockedNotification(MojServiceMessage *msg, const MojObject& response, MojErr err, bool debounce) { LOG_AM_TRACE("Entering function %s", __FUNCTION__); if (err == MojErrNone) { LOG_AM_DEBUG("[Activity %llu] Power lock successfully %s", m_activity.lock()->GetId(), debounce ? "debounced" : "removed"); // reset the call *before* the unlocked notification; if // we end up requeuing the activity due to a transient, we may end // up sending a new call. m_call.reset(); m_currentState = PowerUnlocked; m_activity.lock()->PowerUnlockedNotification(); } else { LOG_AM_WARNING(MSGID_PWRULK_NOTI_ERR,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Attempt to %s power lock failed, retrying. Error: %s", debounce ? "debounce" : "remove", MojoObjectJson(response).c_str()); m_call.reset(); /* Retry. XXX but if error is "Activity doesn't exist", it's done. */ MojErr err2; if (debounce) { err2 = CreateRemotePowerActivity(true); } else { err2 = RemoveRemotePowerActivity(); } if (err2) { LOG_AM_WARNING(MSGID_PWR_UNLOCK_CREATE_ERR,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Failed to issue command to %s power lock", debounce ? "debounce" : "remove"); /* Not much to do at this point, let the Activity move on * so it doesn't hang. */ LOG_AM_WARNING(MSGID_PWR_UNLOCK_FAKE_NOTI,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Faking power unlocked notification in Noti"); m_currentState = PowerUnlocked; m_activity.lock()->PowerUnlockedNotification(); } } }
ConversionResultFlags ji64_to_i32(int64_t value, int32_t *result) { if (value > PJSON_MAX_INT) { PJ_LOG_WARN("PBNJSON_INT64_OO_INT32_RANGE", 1, PMLOGKFV("VALUE", "%"PRId64, value), "overflow converting %"PRId64 " to int32", value); *result = PJSON_MAX_INT; return CONV_POSITIVE_OVERFLOW; } if (value < PJSON_MIN_INT) { PJ_LOG_WARN("PBNJSON_INT64_OO_INT32_RANGE", 1, PMLOGKFV("VALUE", "%"PRId64, value), "overflow converting %"PRId64 " to int32", value); *result = PJSON_MIN_INT; return CONV_NEGATIVE_OVERFLOW; } *result = (int32_t) value; return CONV_OK; }
boost::shared_ptr<Requirement> TelephonyProxy::InstantiateRequirement( boost::shared_ptr<Activity> activity, const std::string& name, const MojObject& value) { LOG_TRACE("Entering function %s", __FUNCTION__); LOG_DEBUG("Instantiating [Requirement %s] for [Activity %llu]", name.c_str(), activity->GetId()); if (name == "telephony") { if ((value.type() == MojObject::TypeBool) && value.boolValue()) { boost::shared_ptr<ListedRequirement> req = boost::make_shared<BasicCoreListedRequirement>( activity, m_telephonyRequirementCore, m_telephonyRequirementCore->IsMet()); m_telephonyRequirements.push_back(*req); return req; } else { throw std::runtime_error("If a 'telephony' requirement is " "specified, the only legal value is 'true'"); } } else { LOG_ERROR(MSGID_TIL_UNKNOWN_REQ, 3, PMLOGKS("MANAGER", GetName().c_str()), PMLOGKS("REQ",name.c_str()), PMLOGKFV("ACTIVITY_ID","%llu",activity->GetId()), "does not know how to instantiate Requirement" ); throw std::runtime_error("Attempt to instantiate unknown requirement"); } }
inline void _lshandle_validate(LSHandle *sh) { if (sh && sh->history.magic_state_num != LSHANDLE_MAGIC_STATE_VALID) { Dl_info create_info; Dl_info destroy_info; bool create_info_valid = false; bool destroy_info_valid = false; if (sh->history.creator_ret_addr) { create_info_valid = dladdr(sh->history.creator_ret_addr, &create_info); } if (sh->history.destroyer_ret_addr) { destroy_info_valid = dladdr(sh->history.destroyer_ret_addr, &destroy_info); } LOG_LS_ERROR(MSGID_LS_INVALID_HANDLE, 5, PMLOGKFV("HANDLER", "%p", sh), PMLOGKS("CREATE_DLI_FNAME", create_info_valid ? create_info.dli_fname : "(unknown)"), PMLOGKS("CREATE_DLI_SNAME", create_info_valid ? create_info.dli_sname : "(unknown)"), PMLOGKS("DESTR_DLI_FNAME", destroy_info_valid ? destroy_info.dli_fname : "(unknown)"), PMLOGKS("DESTR_DLI_SNAME", destroy_info_valid ? destroy_info.dli_sname : "(unknown)"), "%s: Invalid handle", __func__); LS_ASSERT(!"Invalid LSHandle"); } }
boost::shared_ptr<Requirement> ConnectionManagerProxy::InstantiateRequirement( boost::shared_ptr<Activity> activity, const std::string& name, const MojObject& value) { LOG_TRACE("Entering function %s", __FUNCTION__); LOG_DEBUG("Instantiating [Requirement %s] for [Activity %llu]", name.c_str(), activity->GetId()); if (name == "internet") { if ((value.type() == MojObject::TypeBool) && value.boolValue()) { boost::shared_ptr<ListedRequirement> req = boost::make_shared<BasicCoreListedRequirement>( activity, m_internetRequirementCore, m_internetRequirementCore->IsMet()); m_internetRequirements.push_back(*req); return req; } else { throw std::runtime_error("If an 'internet' requirement is " "specified, the only legal value is 'true'"); } } else if (name == "internetConfidence") { return InstantiateConfidenceRequirement(activity, m_internetConfidenceCores, m_internetConfidenceRequirements, value); } else if (name == "wan") { if ((value.type() == MojObject::TypeBool) && value.boolValue()) { boost::shared_ptr<ListedRequirement> req = boost::make_shared<BasicCoreListedRequirement>( activity, m_wanRequirementCore, m_wanRequirementCore->IsMet()); m_wanRequirements.push_back(*req); return req; } else { throw std::runtime_error("If an 'wan' requirement is " "specified, the only legal value is 'true'"); } } else if (name == "wanConfidence") { return InstantiateConfidenceRequirement(activity, m_wanConfidenceCores, m_wanConfidenceRequirements, value); } else if (name == "wifi") { if ((value.type() == MojObject::TypeBool) && value.boolValue()) { boost::shared_ptr<ListedRequirement> req = boost::make_shared<BasicCoreListedRequirement>( activity, m_wifiRequirementCore, m_wifiRequirementCore->IsMet()); m_wifiRequirements.push_back(*req); return req; } else { throw std::runtime_error("If an 'wifi' requirement is " "specified, the only legal value is 'true'"); } } else if (name == "wifiConfidence") { return InstantiateConfidenceRequirement(activity, m_wifiConfidenceCores, m_wifiConfidenceRequirements, value); } else { LOG_ERROR(MSGID_REQUIREMENT_INSTANTIATE_FAIL , 3, PMLOGKS("Manager",GetName().c_str()), PMLOGKFV("Activity","%llu",activity->GetId()), PMLOGKS("Requirement",name.c_str()), ""); throw std::runtime_error("Attempt to instantiate unknown requirement"); } }
void PowerdPowerActivity::End() { LOG_AM_TRACE("Entering function %s", __FUNCTION__); LOG_AM_DEBUG("[Activity %llu] Unlocking power", m_activity.lock()->GetId()); if ((m_currentState == PowerUnlocked) || (m_targetState == PowerUnlocked)) { return; } if (m_timeout) { m_timeout.reset(); } /* If there's a command in flight, cancel it. */ if (m_call) { m_call.reset(); } m_targetState = PowerUnlocked; m_currentState = PowerUnknown; bool debounce = m_activity.lock()->IsPowerDebounce(); MojErr err; if (debounce) { err = CreateRemotePowerActivity(true); } else { err = RemoveRemotePowerActivity(); } if (err) { LOG_AM_ERROR(MSGID_PWR_UNLOCK_CREATE_FAIL,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Failed to issue command to %s power unlock", debounce ? "debounce" : "remove"); /* Fake it so the Activity doesn't stall - the lock will fall off * on its own... not that that's a good thing, but better than * nothing. */ LOG_AM_WARNING(MSGID_PWR_UNLOCK_FAKE_NOTI,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Faking power unlocked notification"); m_currentState = PowerUnlocked; m_activity.lock()->PowerUnlockedNotification(); } }
boost::shared_ptr<Requirement> PowerdProxy::InstantiateRequirement( boost::shared_ptr<Activity> activity, const std::string& name, const MojObject& value) { LOG_TRACE("Entering function %s", __FUNCTION__); LOG_DEBUG("Instantiating [Requirement %s] for [Activity %llu]", name.c_str(), activity->GetId()); if (name == "charging") { if ((value.type() != MojObject::TypeBool) || !value.boolValue()) { throw std::runtime_error("A \"charging\" requirement must specify " "'true' if present"); } boost::shared_ptr<ListedRequirement> req = boost::make_shared<BasicCoreListedRequirement>( activity, m_chargingRequirementCore, m_chargingRequirementCore->IsMet()); m_chargingRequirements.push_back(*req); return req; } else if (name == "docked") { if ((value.type() != MojObject::TypeBool) || !value.boolValue()) { throw std::runtime_error("A \"docked\" requirement must specify " "'true' if present"); } boost::shared_ptr<ListedRequirement> req = boost::make_shared<BasicCoreListedRequirement>( activity, m_dockedRequirementCore, m_dockedRequirementCore->IsMet()); m_dockedRequirements.push_back(*req); return req; } else if (name == "battery") { if ((value.type() != MojObject::TypeInt) || (value.intValue() < 0) || (value.intValue() > 100)) { throw std::runtime_error("A \"battery\" requirement must specify " "a value between 0 and 100"); } MojInt64 percent = value.intValue(); boost::shared_ptr<BatteryRequirement> req = boost::make_shared<BatteryRequirement>(activity, percent, boost::dynamic_pointer_cast<PowerdProxy, RequirementManager>(shared_from_this()), (m_batteryPercent >= percent)); m_batteryRequirements.insert(*req); return req; } else { LOG_ERROR(MSGID_UNKNOW_REQUIREMENT,3, PMLOGKS("MANAGER",GetName().c_str()), PMLOGKS("REQUIREMENT",name.c_str()), PMLOGKFV("Activity","%llu",activity->GetId()), "does not know how to instantiate "); throw std::runtime_error("Attempt to instantiate unknown requirement"); } }
ConversionResultFlags ji64_to_double(int64_t value, double *result) { CHECK_POINTER_RETURN_VALUE(result, CONV_BAD_ARGS); if (value > PJSON_MAX_INT_IN_DBL || value < PJSON_MIN_INT_IN_DBL) { PJ_LOG_WARN("PBNJSON_INT_TO_DBL_CONV_WARN", 1, PMLOGKFV("VALUE", "%"PRId64, value), "conversion of integer %"PRId64 " to a double will result in precision loss when doing reverse", value); *result = (double)value; return CONV_PRECISION_LOSS; } *result = (double)value; return CONV_OK; }
void PowerdPowerActivity::TimeoutNotification() { LOG_AM_TRACE("Entering function %s", __FUNCTION__); LOG_AM_DEBUG("[Activity %llu] Attempting to update power lock", m_activity.lock()->GetId()); #ifdef ACTIVITYMANAGER_RENEW_POWER_ACTIVITIES MojErr err = CreateRemotePowerActivity(); if (err) { LOG_AM_ERROR(MSGID_PWR_ACTIVITY_CREATE_ERR,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Failed to issue command to update power lock"); m_timeout->Arm(); } #else LOG_AM_WARNING(MSGID_PWR_TIMEOUT_NOTI,2, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), PMLOGKFV("LOCKDURATION","%d",PowerActivityLockDuration), "Power Activity exceeded maximum length of seconds, not being renewed"); #endif }
/* * networkStatusQuery * * { * "extended" : { * ... * "state" : "noservice" | "limited" | "service" * ... * } * } * */ void TelephonyProxy::NetworkStatusUpdate(MojServiceMessage *msg, const MojObject& response, MojErr err) { LOG_TRACE("Entering function %s", __FUNCTION__); LOG_DEBUG("Network status update message: %s", MojoObjectJson(response).c_str()); if (err != MojErrNone) { if (MojoCall::IsPermanentFailure(msg, response, err)) { LOG_WARNING(MSGID_TIL_NWSTATUS_QUERY_ERR,0, "TIL experienced an uncorrectable failure : %s", MojoObjectJson(response).c_str()); m_networkStatusQuery.reset(); } else { LOG_WARNING(MSGID_TIL_NWSTATUS_QUERY_RETRY, 0, "Subscription to TIL failed, retrying - %s", MojoObjectJson(response).c_str() ); m_networkStatusQuery->Call(); } return; } MojObject extended; bool found; found = response.get(_T("extended"), extended); if (!found) { /* Way to have 2 different formats for the same thing! First * response names the property "extended". All subsequent ones * name it "eventNetwork". */ found = response.get(_T("eventNetwork"), extended); } if (found) { MojString status; MojErr err2; err2 = extended.get(_T("state"), status, found); if (err2) { LOG_WARNING(MSGID_TIL_NWSTATE_ERR, 1 , PMLOGKFV("NWSTATE","%d",err2), "Error attempting to retrieve network state"); } else if (found) { if (status == "service") { m_haveTelephonyService = true; } else { m_haveTelephonyService = false; } UpdateTelephonyState(); } else { LOG_WARNING(MSGID_TIL_NO_NWSTATE, 0 , "Network status update message did not include network state: %s", MojoObjectJson(response).c_str()); } } }
MojErr MojDbLunaServiceDb::recoverDb(MojDbEnv* env, const MojChar* dir, const MojObject& conf) { MojErr err; if (m_recoveryScriptPath.empty()) { LOG_ERROR(MSGID_LUNA_SERVICE_DB_OPEN,0, "No recovery script, close database"); return MojErrDbFatal; } int recoveryResult = system(m_recoveryScriptPath.data()); if (recoveryResult != 0) { LOG_ERROR(MSGID_LUNA_SERVICE_DB_OPEN, 3, PMLOGKS("recoveryScript", m_recoveryScriptPath.data()), PMLOGKFV("scriptExecResult", "%i", recoveryResult), PMLOGKS("dbdir", dir), "Can't recovery database with help of recovery script"); return MojErrDbFatal; // close database and stop process } LOG_INFO(MSGID_LUNA_SERVICE_DB_OPEN, 0, "Recovery database success, reopen database" ); err = openDb(env, dir, conf); if (err != MojErrNone) { MojString msg; MojErrToString(err, msg); LOG_ERROR(MSGID_LUNA_SERVICE_DB_OPEN, 3, PMLOGKS("dbdir", dir), PMLOGKS("dbdata", msg.data()), PMLOGKFV("dberror", "%d", err), "Error re-opening database after recovery"); return err; } return MojErrNone; }
void PowerdPowerActivity::Begin() { LOG_AM_TRACE("Entering function %s", __FUNCTION__); LOG_AM_DEBUG("[Activity %llu] Locking power on", m_activity.lock()->GetId()); if ((m_currentState == PowerLocked) || (m_targetState == PowerLocked)) { return; } if (m_timeout) { m_timeout.reset(); } /* If there's a command in flight, cancel it. */ if (m_call) { m_call.reset(); } m_targetState = PowerLocked; m_currentState = PowerUnknown; MojErr err = CreateRemotePowerActivity(); if (err) { LOG_AM_ERROR(MSGID_PWR_LOCK_CREATE_FAIL,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Failed to issue command to create power lock"); /* Fake it so the Activity doesn't stall */ LOG_AM_WARNING(MSGID_PWR_LOCK_FAKE_NOTI,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Faking power locked notification"); m_currentState = PowerLocked; m_activity.lock()->PowerLockedNotification(); } }
void ConnectionManagerProxy::UpdateConfidenceRequirements( boost::shared_ptr<RequirementCore> *confidenceCores, RequirementList *confidenceLists, int confidence) { if (((confidence < 0) || (confidence >= ConnectionConfidenceMax)) && (confidence != ConnectionConfidenceUnknown)) { LOG_WARNING(MSGID_UNKNOWN_CONN_CONFIDENCE_LEVEL, 1, PMLOGKFV("conn_confidence_level","%d",confidence), "Unknown connection confidence level seen attempting to update confidence requirements"); return; } MojString& confidenceName = (confidence == ConnectionConfidenceUnknown) ? ConnectionConfidenceUnknownName : ConnectionConfidenceNames[confidence]; for (int i = 0; i < ConnectionConfidenceMax; ++i) { confidenceCores[i]->SetCurrentValue(MojObject(confidenceName)); if (confidence < i) { if (confidenceCores[i]->IsMet()) { confidenceCores[i]->Unmet(); std::for_each(confidenceLists[i].begin(), confidenceLists[i].end(), boost::mem_fn(&Requirement::Unmet)); } else { std::for_each(confidenceLists[i].begin(), confidenceLists[i].end(), boost::mem_fn(&Requirement::Updated)); } } else { if (!confidenceCores[i]->IsMet()) { confidenceCores[i]->Met(); std::for_each(confidenceLists[i].begin(), confidenceLists[i].end(), boost::mem_fn(&Requirement::Met)); } else { std::for_each(confidenceLists[i].begin(), confidenceLists[i].end(), boost::mem_fn(&Requirement::Updated)); } } } }
MojErr MojDbIndex::addWatch(const MojDbQueryPlan& plan, MojDbCursor& cursor, MojDbWatcher* watcher, MojDbReq& req) { LOG_TRACE("Entering function %s", __FUNCTION__); MojAssert(watcher); // TODO: use interval tree instead of vector for watches MojThreadWriteGuard guard(m_lock); MojErr err = m_watcherVec.push(watcher); MojErrCheck(err); // update count map watcher->domain(req.domain()); WatcherMap::Iterator iter; err = m_watcherMap.find(req.domain(), iter); MojErrCheck(err); if (iter == m_watcherMap.end()) { err = m_watcherMap.put(req.domain(), 1); MojErrCheck(err); } else { iter.value() += 1; if (iter.value() > WatchWarningThreshold) { LOG_WARNING(MSGID_MOJ_DB_INDEX_WARNING, 4, PMLOGKS("domain", req.domain().data()), PMLOGKFV("iter", "%zd", iter.value()), PMLOGKS("kindId", m_kind->id().data()), PMLOGKS("name", m_name.data()), "db:'domain' has 'iter' watches open on index 'kindId - name'"); } } LOG_DEBUG("[db_mojodb] DbIndex_addWatch - '%s' on index '%s - %s'", req.domain().data(), m_kind->id().data(), m_name.data()); // drop lock before acquiring watcher mutex in init guard.unlock(); watcher->init(this, plan.ranges(), plan.desc(), false); return MojErrNone; }
MojErr MojDbLunaServiceDb::open(MojGmainReactor& reactor, MojDbEnv* env, const MojChar* serviceName, const MojChar* dir, const MojObject& conf) { LOG_TRACE("Entering function %s", __FUNCTION__); // open service MojErr err = m_service.open(serviceName); MojErrCheck(err); err = m_service.attach(reactor.impl()); MojErrCheck(err); // open handler err = m_handler->open(); MojErrCheck(err); err = m_service.addCategory(MojDbServiceDefs::Category, m_handler.get()); MojErrCheck(err); LOG_DEBUG("[MojDb] service name: %s", serviceName); // open db err = openDb(env, dir, conf); if (err != MojErrNone) { MojString msg; MojErrToString(err, msg); LOG_WARNING(MSGID_LUNA_SERVICE_DB_OPEN, 3, PMLOGKS("dbdir", dir), PMLOGKS("dbdata", msg.data()), PMLOGKFV("dberror", "%d", err), "Can't open database"); err = recoverDb(env, dir, conf); MojErrCheck(err); } return err; }
void PowerdProxy::ChargerStatusSignal(MojServiceMessage *msg, const MojObject& response, MojErr err) { LOG_TRACE("Entering function %s", __FUNCTION__); LOG_DEBUG("Received charger status signal: %s", MojoObjectJson(response).c_str()); if (err != MojErrNone) { m_chargerStatusSubscribed = false; if (MojoCall::IsPermanentFailure(msg, response, err)) { LOG_WARNING(MSGID_CHRGR_STATUS_SIG_FAIL,0, "Subscription to charger status signal experienced an uncorrectable failure: %s", MojoObjectJson(response).c_str()); m_chargerStatus.reset(); } else { LOG_WARNING(MSGID_CHRGR_SIG_ENABLE,0, "Subscription to charger status signal failed, resubscribing: %s", MojoObjectJson(response).c_str()); EnableChargerSignals(); } return; } if (!m_chargerStatusSubscribed) { m_chargerStatusSubscribed = true; TriggerChargerStatus(); } /* Not all responses will contain charger information... for example, * the initial subscription result. */ MojString chargerType; bool found = false; MojErr err2 = response.get(_T("type"), chargerType, found); if (err2) { LOG_ERROR(MSGID_CHRGR_SIG_NO_TYPE, 1,PMLOGKFV("ERROR","%d",err2), "Error retrieving charger type from charger status signal response"); return; } else if (found) { bool connected; found = response.get(_T("connected"), connected); if (!found) { LOG_WARNING(MSGID_CHRGR_NOT_CONNECTED,1,PMLOGKS("TYPE",chargerType.data()), "Charger type found, but not it's connected"); return; } if (chargerType == "usb") { m_usbChargerConnected = connected; } else if (chargerType == "inductive") { m_inductiveChargerConnected = connected; } else { LOG_WARNING(MSGID_CHRGR_TYPE_UNKNOWN, 1, PMLOGKS("TYPE",chargerType.data()), "Unknown charger type"); return; } found = false; MojString name; err2 = response.get(_T("name"), name, found); if (err2) { LOG_ERROR(MSGID_CHRGR_NO_NAME,2, PMLOGKS("TYPE",chargerType.data()), PMLOGKFV("ERR", "%d", err2), "Error retrieving the specific name of charger"); } else if (found) { if (name == "puck") { m_onPuck = connected; } } if (m_onPuck) { if (!m_dockedRequirementCore->IsMet()) { LOG_DEBUG("Device is now docked"); m_dockedRequirementCore->Met(); std::for_each(m_dockedRequirements.begin(), m_dockedRequirements.end(), boost::mem_fn(&Requirement::Met)); } } else { if (m_dockedRequirementCore->IsMet()) { LOG_DEBUG("Device is no longer docked"); m_dockedRequirementCore->Unmet(); std::for_each(m_dockedRequirements.begin(), m_dockedRequirements.end(), boost::mem_fn(&Requirement::Unmet)); } } if (m_inductiveChargerConnected || m_usbChargerConnected) { if (!m_chargingRequirementCore->IsMet()) { LOG_DEBUG("Device is now charging"); m_chargingRequirementCore->Met(); std::for_each(m_chargingRequirements.begin(), m_chargingRequirements.end(), boost::mem_fn(&Requirement::Met)); } } else { if (m_chargingRequirementCore->IsMet()) { LOG_DEBUG("Device is no longer charging"); m_chargingRequirementCore->Unmet(); std::for_each(m_chargingRequirements.begin(), m_chargingRequirements.end(), boost::mem_fn(&Requirement::Unmet)); } } } }
void PowerdPowerActivity::PowerLockedNotification(MojServiceMessage *msg, const MojObject& response, MojErr err) { LOG_AM_TRACE("Entering function %s", __FUNCTION__); if (err == MojErrNone) { if (m_currentState != PowerLocked) { LOG_AM_DEBUG("[Activity %llu] Power lock successfully created", m_activity.lock()->GetId()); m_currentState = PowerLocked; m_activity.lock()->PowerLockedNotification(); } else { LOG_AM_DEBUG("[Activity %llu] Power lock successfully updated", m_activity.lock()->GetId()); } if (!m_timeout) { m_timeout = boost::make_shared<Timeout<PowerdPowerActivity> >( boost::dynamic_pointer_cast<PowerdPowerActivity, PowerActivity>( shared_from_this()), PowerActivityLockUpdateInterval, &PowerdPowerActivity::TimeoutNotification); } m_timeout->Arm(); m_call.reset(); } else { if (m_currentState != PowerLocked) { LOG_AM_WARNING(MSGID_PWRLK_NOTI_CREATE_FAIL,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Attempt to create power lock failed, retrying. Error %s", MojoObjectJson(response).c_str()); } else { LOG_AM_WARNING(MSGID_PWRLK_NOTI_UPDATE_FAIL,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Attempt to update power lock failed, retrying. Error %s", MojoObjectJson(response).c_str()); } m_call.reset(); /* Retry - powerd may have restarted. */ MojErr err2 = CreateRemotePowerActivity(); if (err2) { LOG_AM_WARNING(MSGID_PWR_LOCK_CREATE_FAIL,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Failed to issue command to create power lock in Noti" ); /* If power was not currently locked, fake the create so the * Activity doesn't hang */ if (m_currentState != PowerLocked) { LOG_AM_WARNING(MSGID_PWR_LOCK_FAKE_NOTI,1, PMLOGKFV("Activity","%llu",m_activity.lock()->GetId()), "Faking power locked notification in noti"); m_currentState = PowerLocked; m_activity.lock()->PowerLockedNotification(); } } } }
static void alarm_read_db(void) { bool retVal; xmlDocPtr db = xmlReadFile(gAlarmQueue->alarm_db, NULL, 0); if (!db) { return; } xmlNodePtr cur = xmlDocGetRootElement(db); xmlNodePtr sub; if (!cur) { return; } sub = cur->children; while (sub != NULL) { if (!xmlStrcmp(sub->name, (const xmlChar *)"alarm")) { xmlChar *id = xmlGetProp(sub, (const xmlChar *)"id"); xmlChar *key = xmlGetProp(sub, (const xmlChar *)"key"); xmlChar *expiry = xmlGetProp(sub, (const xmlChar *)"expiry"); xmlChar *calendar = xmlGetProp(sub, (const xmlChar *)"calendar"); xmlChar *service = xmlGetProp(sub, (const xmlChar *)"serviceName"); xmlChar *app = xmlGetProp(sub, (const xmlChar *)"applicationName"); if (!id || !expiry) { goto clean_round; } unsigned long expiry_secs = 0; uint32_t alarmId = 0; bool isCalendar = false; if (expiry) { expiry_secs = atol((const char *)expiry); } if (id) { alarmId = atoi((const char *)id); } if (calendar) { isCalendar = atoi((const char *)calendar) > 0; } retVal = alarm_queue_add(alarmId, (const char *)key, isCalendar, expiry_secs, (const char *)service, (const char *)app, false, NULL); if (!retVal) { SLEEPDLOG_WARNING(MSGID_ALARM_NOT_SET, 3, PMLOGKFV(ALARM_ID, "%d", alarmId), PMLOGKS(SRVC_NAME, service), PMLOGKS(APP_NAME, app), "could not add alarm"); } clean_round: xmlFree(expiry); xmlFree(service); xmlFree(app); } sub = sub->next; } xmlFreeDoc(db); }
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(); } }
ConversionResultFlags parseJSONNumber(raw_buffer *str, int64_t *integerPortion, int64_t *exponentPortion, int64_t *decimalPortion, int64_t *decimalLeadingZeros) { size_t i = 0; int integerMultiplier = 1; int exponentMultiplier = 1; int64_t exponent = 0; int64_t fraction = 0; int64_t fractionFactor = 0; int64_t trailingZeros = 0; bool validDecimal; int64_t temp; ConversionResultFlags result = CONV_OK; *integerPortion = 0; if (str->m_len == 0) { result = CONV_NOT_A_NUM; goto fast_stop; } switch (str->m_str[i]) { case '-': integerMultiplier = -1; i++; goto parse_integer_portion; case '0': i++; if (i >= str->m_len) goto fast_stop; switch(str->m_str[i]) { case '.': goto parse_decimal_portion; case 'e': case 'E': goto parse_exponent_portion; default: result = CONV_NOT_A_NUM; goto fast_stop; } case '1'...'9': goto parse_integer_portion; default: goto not_a_number; } parse_integer_portion: assert(integerMultiplier == 1 || integerMultiplier == -1); assert(exponent == 0); for (; i < str->m_len; i++) { switch (str->m_str[i]) { case 'e': case 'E': goto parse_exponent_portion; case '.': goto parse_decimal_portion; case '0'...'9': if (exponent == 0) { if (integerMultiplier == 1) { if (*integerPortion > (INT64_MAX / 10)) exponent = 1; } else { if (*integerPortion < (INT64_MIN) / 10) exponent = 1; } if (exponent == 0) { temp = *integerPortion * 10 + integerMultiplier * (str->m_str[i] - '0'); if (UNLIKELY(temp * integerMultiplier < 0)) { // sign flipped - overflow exponent = 1; } else { *integerPortion = temp; } } } else { if (exponent++ == INT64_MAX) return CONV_PRECISION_LOSS | (integerMultiplier == 1 ? CONV_POSITIVE_INFINITY : CONV_NEGATIVE_INFINITY); } break; default: PJ_LOG_WARN("PBNJSON_PNUM_UNXPCTD_CHAR1", 1, PMLOGKFV("CHAR", "%c", str->m_str[i]), "Unexpected character %d('%c') in '%.*s' at %zu", (int)str->m_str[i], str->m_str[i], (int)str->m_len, str->m_str, i); goto not_a_number; } } goto finish_parse; parse_decimal_portion: validDecimal = false; assert(fraction == 0); assert(fractionFactor == 0); assert(trailingZeros == 0); if (str->m_str[i] != '.') { assert(false); PJ_LOG_WARN("PBNJSON_PNUM_UNXPCTD_CHAR2", 1, PMLOGKFV("CHAR", "%c", str->m_str[i]), "Unexpected character %d('%c') in '%.*s' at %zu", (int)str->m_str[i], str->m_str[i], (int) str->m_len, str->m_str, i); goto not_a_number; } i++; for (; i < str->m_len; i++) { switch(str->m_str[i]) { case 'e': case 'E': goto parse_exponent_portion; case '0'...'9': validDecimal = true; if (str->m_str[i] == '0') { // short-circuit - trailing 0s are ignored if that's what they are. trailingZeros ++; break; } if (UNLIKELY(fractionFactor == INT64_MAX)) { assert(false); // this will only become an issue if 10^INT64_MAX < (2^((sizeof(fraction)*8) - 1) - 1) // which will never happen PJ_LOG_ERR("PBNJSON_FRACTION_ERR", 1, PMLOGKS("STRING", str->m_str), "Internal error for input: %.*s", (int)str->m_len, str->m_str); return CONV_GENERIC_ERROR; } while (trailingZeros != 0) { temp = fraction * 10; if (temp < 0) goto skip_remaining_decimal; trailingZeros--; fractionFactor++; fraction = temp; } fractionFactor++; if (fraction != INT64_MAX) { temp = fraction * 10 + (str->m_str[i] - '0'); if (UNLIKELY(temp < 0)) { fractionFactor--; goto skip_remaining_decimal; } else { fraction = temp; } } break; default: PJ_LOG_WARN("PBNJSON_PNUM_UNXPCTD_CHAR3", 1, PMLOGKFV("CHAR", "%c", str->m_str[i]), "Unexpected character %d('%c') in '%.*s' at %zu", (int)str->m_str[i], str->m_str[i], (int)str->m_len, str->m_str, i); goto not_a_number; } } if (UNLIKELY(!validDecimal)) { PJ_LOG_WARN("PBNJSON_UNXPCTD_EOS", 0, "Unexpected end of string at %zu in '%.*s'", i, (int)str->m_len, str->m_str); goto not_a_number; } goto finish_parse; skip_remaining_decimal: assert(str->m_str[i] >= '0'); assert(str->m_str[i] <= '9'); result |= CONV_PRECISION_LOSS; for (; i < str->m_len; i++) { if (str->m_str[i] >= '0' && str->m_str[i] <= '9') continue; if (str->m_str[i] == 'e' || str->m_str[i] == 'E') goto parse_exponent_portion; PJ_LOG_WARN("PBNJSON_PNUM_UNXPCTD_CHAR4", 1, PMLOGKFV("CHAR", "%c", str->m_str[i]), "Unexpected character %d('%c') in '%.*s' at %zu", (int)str->m_str[i], str->m_str[i], (int)str->m_len, str->m_str, i); goto not_a_number; } assert(i == str->m_len); goto finish_parse; parse_exponent_portion: assert(exponent >= 0); if (UNLIKELY(str->m_str[i] != 'e' && str->m_str[i] != 'E')) { // problem with the state machine assert(false); PJ_LOG_ERR("PBNJSON_NO_EXPONENT", 1, PMLOGKS("STRING", str->m_str), "Expecting an exponent but didn't get one at %zu in '%.*s'", i, (int)str->m_len, str->m_str); return CONV_GENERIC_ERROR; } i++; switch (str->m_str[i]) { case '-': i++; exponentMultiplier = -1; break; case '+': i++; case '0'...'9': exponentMultiplier = 1; break; default: PJ_LOG_WARN("PBNJSON_PNUM_UNXPCTD_CHAR5", 1, PMLOGKFV("CHAR", "%c", str->m_str[i]), "Unexpected character %d('%c') in '%.*s' at %zu", (int)str->m_str[i], str->m_str[i], (int)str->m_len, str->m_str, i); goto not_a_number; } assert(exponentMultiplier == 1 || exponentMultiplier == -1); for (; i < str->m_len; i++) { switch (str->m_str[i]) { case '0'...'9': if (exponentMultiplier == 1) { if (UNLIKELY(exponent > (INT64_MAX / 10))) goto exponent_overflow; } else if (exponentMultiplier == -1) { if (UNLIKELY(exponent < (INT64_MIN / 10))) goto exponent_overflow; } exponent *= 10; exponent += exponentMultiplier * (str->m_str[i] - '0'); if (exponent * exponentMultiplier < 0) { goto exponent_overflow; } break; default: PJ_LOG_WARN("PBNJSON_PNUM_UNXPCTD_CHAR6", 1, PMLOGKFV("CHAR", "%c", str->m_str[i]), "Unexpected character %d('%c') in '%.*s' at %zu", (int)str->m_str[i], str->m_str[i], (int)str->m_len, str->m_str, i); goto not_a_number; } } assert(i == str->m_len); goto finish_parse; exponent_overflow: // overflow of a 64-bit exponent - +/- infinity or 0 it is. assert(exponent > (INT64_MAX / 10 - 10) || exponent < (INT64_MIN / 10 + 10)); if (exponentMultiplier == 1) { exponent = INT64_MAX; if (integerMultiplier == 1) { *integerPortion = INT64_MAX; result |= CONV_POSITIVE_INFINITY; } else { *integerPortion = INT64_MIN; result |= CONV_NEGATIVE_INFINITY; } } else { result |= CONV_PRECISION_LOSS; exponent = INT64_MIN; *integerPortion = 0; } goto finish_parse; finish_parse: if (trailingZeros) { PJ_LOG_DBG("%"PRId64 " unnecessary 0s in fraction portion of '%.*s'", trailingZeros, (int)str->m_len, str->m_str); } if (fraction == 0) { assert(fractionFactor == 0); } if (*integerPortion == 0 && (decimalPortion == NULL || fraction == 0)) { // shortcut - exponent is redundant if the number is 0.something but we're // ignoring the decimal (or there's no fractional portion) exponent = 0; if (fraction != 0) { result |= CONV_PRECISION_LOSS; } } // can't really do this anyways - it would require us shifting values into or out // of the fractional component when we adjust the integerPortion by the exponent. // internally, we would never use this case anyways because if we care what the // fraction is (i.e. we're converting to a floating point), we'll provide the exponent // pointer anyways if (exponentPortion == NULL && exponent != 0 && fraction != 0) { result |= CONV_PRECISION_LOSS; fraction = 0; fractionFactor = 0; } if (!exponentPortion) { if (*integerPortion != 0) { if (exponent > 0) { while (exponent) { if (*integerPortion > INT64_MAX / 10) { assert(integerMultiplier == 1); result |= CONV_POSITIVE_OVERFLOW; *integerPortion = INT64_MAX; break; } else if (*integerPortion < INT64_MIN / 10) { assert(integerMultiplier == -1); result |= CONV_NEGATIVE_OVERFLOW; *integerPortion = INT64_MIN; break; } if (*integerPortion != 0) assert(*integerPortion * 10 > 0); *integerPortion *= 10; exponent--; } } else if (exponent < 0) { if (fraction) { result |= CONV_PRECISION_LOSS; goto lost_precision; } while (exponent) { if (*integerPortion % 10 != 0) { result |= CONV_PRECISION_LOSS; goto lost_precision; } *integerPortion /= 10; exponent++; } lost_precision: while (exponent++ && *integerPortion > 0) *integerPortion /= 10; } } } else { *exponentPortion = exponent; } if (!decimalPortion) { if (fraction != 0) { result |= CONV_PRECISION_LOSS; } } else { *decimalPortion = fraction; *decimalLeadingZeros = fractionFactor; } return result; not_a_number: return CONV_NOT_A_NUM; fast_stop: if (exponentPortion) *exponentPortion = exponent; if (decimalPortion) *decimalPortion = fraction; if (decimalLeadingZeros) *decimalLeadingZeros = fractionFactor; return result; }
jvalue_ref jdom_parse_file(const char *file, JSchemaInfoRef schemaInfo, JFileOptimizationFlags flags) { CHECK_POINTER_RETURN_NULL(file); CHECK_POINTER_RETURN_NULL(schemaInfo); int fd; off_t fileSize; raw_buffer input = { 0 }; jvalue_ref result; char *err_msg; fd = open(file, O_RDONLY); if (fd == -1) { goto errno_parse_failure; } if (!file_size(fd, &fileSize)) { goto errno_parse_failure; } input.m_len = fileSize; if (input.m_len != fileSize) { PJ_LOG_ERR("PBNJSON_BIG_FILE", 1, PMLOGKS("FILE", file), "File too big - currently unsupported by this API"); close(fd); } if (flags & JFileOptMMap) { input.m_str = (char *)mmap(NULL, input.m_len, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, fd, 0); if (input.m_str == NULL || input.m_str == MAP_FAILED) { goto errno_parse_failure; } } else { input.m_str = (char *)malloc(input.m_len + 1); if (input.m_len != read(fd, (char *)input.m_str, input.m_len)) { goto errno_parse_failure; } ((char *)input.m_str)[input.m_len] = 0; } result = jdom_parse(input, DOMOPT_INPUT_OUTLIVES_WITH_NOCHANGE, schemaInfo); return_result: close(fd); if (UNLIKELY(!jis_valid(result))) { if (input.m_str) { if (flags & JFileOptMMap) { munmap((void *)input.m_str, input.m_len); } else { free((void *)input.m_str); } } } else { result->m_backingBuffer = input; result->m_backingBufferMMap = flags & JFileOptMMap; } return result; errno_parse_failure: err_msg = strdup(strerror(errno)); PJ_LOG_WARN("PBNJSON_PARCE_ERR", 3, PMLOGKS("FILE", file), PMLOGKFV("ERRNO", "%d", errno), PMLOGKS("ERROR", err_msg), "Attempt to parse json document '%s' failed (%d) : %s", file, errno, err_msg); free(err_msg); result = jinvalid(); goto return_result; }