X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fserver%2Fworker_thread.cc;h=b623a2c112c5d7dd3b9f022303cd37ee4fd46b4c;hb=54073ac20bd49b3d664527b7f13b04290152e268;hp=08f292949ffdcb17953476156dbd5c625f2a2311;hpb=efa99f2893bd7d827d7ff5bed76c24db5d1d63de;p=platform%2Fcore%2Fappfw%2Fpkgmgr-info.git diff --git a/src/server/worker_thread.cc b/src/server/worker_thread.cc index 08f2929..b623a2c 100644 --- a/src/server/worker_thread.cc +++ b/src/server/worker_thread.cc @@ -17,20 +17,17 @@ #include "worker_thread.hh" #include +#include #include +#include + #include "abstract_parcelable.hh" -#include "command_request_handler.hh" -#include "create_cache_request_handler.hh" -#include "create_db_request_handler.hh" -#include "db_handle_provider.hh" -#include "get_appinfo_request_handler.hh" -#include "get_cert_request_handler.hh" -#include "get_depinfo_request_handler.hh" -#include "get_pkginfo_request_handler.hh" -#include "query_request_handler.hh" -#include "set_cert_request_handler.hh" -#include "set_pkginfo_request_handler.hh" +#include "cynara_checker.hh" +#include "db_change_observer.hh" +#include "request_handler_factory.hh" +#include "server/database/db_handle_provider.hh" +#include "server/database/update_pending_cache_handler.hh" #include "utils/logging.hh" #include "pkgmgrinfo_debug.h" @@ -44,6 +41,39 @@ #define SQLITE_ENABLE_MEMORY_MANAGEMENT #endif +namespace { + +uid_t globaluser_uid = -1; + +uid_t GetGlobalUID() { + if (globaluser_uid == (uid_t)-1) + globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER); + + return globaluser_uid; +} + +uid_t ConvertUID(uid_t uid) { + if (uid < REGULAR_USER) + return GetGlobalUID(); + else + return uid; +} + +const char PRIVILEGE_PACKAGE_MANAGER_ADMIN[] = + "http://tizen.org/privilege/packagemanager.admin"; + +std::vector GetPrivileges(pkgmgr_common::ReqType type) { + std::vector ret; + if (type == pkgmgr_common::SET_CERT_INFO) + ret.emplace_back(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + else if (type == pkgmgr_common::SET_PKG_INFO) + ret.emplace_back(PRIVILEGE_PACKAGE_MANAGER_ADMIN); + + return ret; +} + +} // namespace + namespace pkgmgr_server { WorkerThread::WorkerThread(unsigned int num) : stop_all_(false) { @@ -71,111 +101,101 @@ bool WorkerThread::PushQueue(std::shared_ptr req) { return true; } -void WorkerThread::Run() { - std::unique_ptr - handler[pkgmgr_common::ReqType::MAX]; - handler[pkgmgr_common::ReqType::GET_PKG_INFO].reset( - new request_handler::GetPkginfoRequestHandler()); - handler[pkgmgr_common::ReqType::GET_APP_INFO].reset( - new request_handler::GetAppinfoRequestHandler()); - handler[pkgmgr_common::ReqType::SET_PKG_INFO].reset( - new request_handler::SetPkginfoRequestHandler()); - handler[pkgmgr_common::ReqType::SET_CERT_INFO].reset( - new request_handler::SetCertRequestHandler()); - handler[pkgmgr_common::ReqType::GET_CERT_INFO].reset( - new request_handler::GetCertRequestHandler()); - handler[pkgmgr_common::ReqType::GET_PKG_DEP_INFO].reset( - new request_handler::GetDepinfoRequestHandler()); - handler[pkgmgr_common::ReqType::QUERY].reset( - new request_handler::QueryRequestHandler()); - handler[pkgmgr_common::ReqType::COMMAND].reset( - new request_handler::CommandRequestHandler()); - handler[pkgmgr_common::ReqType::CREATE_DB].reset( - new request_handler::CreateDBRequestHandler()); - handler[pkgmgr_common::ReqType::CREATE_CACHE].reset( - new request_handler::CreateCacheRequestHandler()); +std::shared_ptr WorkerThread::PopQueue() { + SetMemoryTrimTimer(); + std::unique_lock u(lock_); + cv_.wait(u, [this] { return !this->queue_.empty() || stop_all_; }); + if (stop_all_ && queue_.empty()) + return nullptr; + auto req = queue_.front(); + queue_.pop(); + return req; +} + +void WorkerThread::Run() { + RequestHandlerFactory factory; LOG(DEBUG) << "Initialize request handlers"; while (true) { - std::shared_ptr req; - { - std::unique_lock u(lock_); - cv_.wait(u, [this] { return !this->queue_.empty() || stop_all_; }); - if (stop_all_ && queue_.empty()) - return; - req = PopQueue(); + std::shared_ptr req = PopQueue(); + if (req == nullptr) + return; + + if (!req->GetPrivilegeChecked()) { + if (!req->ReceiveData()) { + LOG(ERROR) << "Fail to receive data"; + continue; + } + + pkgmgr_common::ReqType type = req->GetRequestType(); + if (pkgmgr_common::IsDbWriteRequest(type)) + StopDbChangeListening(); + std::vector privileges = GetPrivileges(type); + if (!CynaraChecker::GetInst().CheckPrivilege(this, req, privileges)) + continue; } - pkgmgr_common::ReqType type = req->GetRequestType(); + auto type = req->GetRequestType(); LOG(WARNING) << "Request type: " << pkgmgr_common::ReqTypeToString(type) - << " pid: " << req->GetSenderPID(); - if (type <= pkgmgr_common::ReqType::REQ_TYPE_NONE - || type >= pkgmgr_common::ReqType::MAX) { - LOG(ERROR) << "Request type is invalid: " << static_cast(type) - << ", pid:" << req->GetSenderPID(); - SendError(req); - + << " pid: " << req->GetSenderPID() << " tid: " << req->GetSenderTID(); + auto handler = factory.GetRequestHandler(type); + if (handler == nullptr) continue; - } try { - handler[type]->SetPID(req->GetSenderPID()); - if (!handler[type]->HandleRequest(req->GetData(), req->GetSize(), - locale_.GetObject())) + handler->PreExec(); + handler->SetUID(ConvertUID(req->GetSenderUID())); + handler->SetPID(req->GetSenderPID()); + if (!handler->HandleRequest(req->DetachData(), req->GetSize(), + locale_.GetObject())) LOG(ERROR) << "Failed to handle request"; + + if (req->SendData(handler->ExtractResult()) == false) + LOG(ERROR) << "Failed to send response pid: " << req->GetSenderPID(); + else + LOG(WARNING) << "Success response pid: " << req->GetSenderPID() + << " tid: " << req->GetSenderTID(); } catch (const std::exception& err) { LOG(ERROR) << "Exception occurred: " << err.what() - << ", pid: " << req->GetSenderPID(); + << ", pid: " << req->GetSenderPID(); SendError(req); - - continue; } catch (...) { LOG(ERROR) << "Exception occurred pid: " << req->GetSenderPID(); SendError(req); - - continue; } - std::vector result_data = handler[type]->ExtractResult(); - if (req->SendData(result_data.data(), result_data.size()) == false) { - LOG(ERROR) << "Failed to send response pid: " << req->GetSenderPID(); - continue; - } - LOG(WARNING) << "Success response pid: " << req->GetSenderPID(); + handler->PostExec(); } } void WorkerThread::SetMemoryTrimTimer() { - static guint timer = 0; - if (timer > 0) - g_source_remove(timer); + std::lock_guard lock(mutex_); + if (timer_ > 0) + g_source_remove(timer_); - timer = g_timeout_add_seconds_full(G_PRIORITY_LOW, 3, - TrimMemory, &timer, NULL); + timer_ = g_timeout_add_seconds_full(G_PRIORITY_LOW, 10, + TrimMemory, this, NULL); } gboolean WorkerThread::TrimMemory(void* data) { LOG(DEBUG) << "Trim memory"; - guint* timer = static_cast(data); - sqlite3_release_memory(-1); - malloc_trim(0); - *timer = 0; - - if (database::DBHandleProvider::IsCrashedWriteRequest()) - database::DBHandleProvider:: - GetInst(getuid()).UnsetMemoryMode(getpid()); - - database::DBHandleProvider:: - GetInst(getuid()).TrimCache(); + auto* h = static_cast(data); + { + std::lock_guard lock(h->mutex_); + h->timer_ = 0; + } - return false; -} + auto crashed_writer_pids = + database::DBHandleProvider::CrashedWriteRequestPIDs(); + if (!crashed_writer_pids.empty()) { + database::UpdatePendingCacheHandler db(getuid(), std::move(crashed_writer_pids), {}); + db.SetLocale(h->locale_.GetObject()); + db.Execute(); + } -std::shared_ptr WorkerThread::PopQueue() { - SetMemoryTrimTimer(); - auto req = queue_.front(); - queue_.pop(); - return req; + sqlite3_release_memory(-1); + malloc_trim(0); + return G_SOURCE_REMOVE; } void WorkerThread::SetLocale(std::string locale) { @@ -184,13 +204,22 @@ void WorkerThread::SetLocale(std::string locale) { locale_.SetObject(std::move(locale)); } -void WorkerThread::SendError(std::shared_ptr req) { +void WorkerThread::SendError(const std::shared_ptr& req) { pkgmgr_common::parcel::AbstractParcelable parcelable( 0, pkgmgr_common::parcel::ParcelableType::Unknown, PMINFO_R_ERROR); tizen_base::Parcel p; p.WriteParcelable(parcelable); - std::vector raw = p.GetRaw(); - req->SendData(&raw[0], raw.size()); + req->SendData(p); +} + +void WorkerThread::StopDbChangeListening() { + auto& db_observer = pkgmgr_common::DbChangeObserver::GetInst(); + + if (db_observer.GetDisposed()) + return; + + LOG(WARNING) << "Try stop listening db change"; + db_observer.StopListening(); } } // namespace pkgmgr_server