#endif
/**
- * @breif Enumeration for the service result.
- * @since_tizen 10.0
- */
- typedef enum {
- SERVICE_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
- SERVICE_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
- SERVICE_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
- SERVICE_ERROR_INVALID_CONTEXT = TIZEN_ERROR_APPLICATION | 0x01, /**< Invalid context */
- SERVICE_ERROR_ALREADY_EXIST = TIZEN_ERROR_FILE_EXISTS, /**<Service already exists */
- } service_error_e;
-
- /**
- * @brief Enumeration for the service state.
+ * @brief The service handle.
* @since_tizen 10.0
- * @see service_create()
+ * @see service_destroy()
+ * @see service_run()
+ * @see service_quit()
+ * @see service_send_message()
*/
- typedef enum {
- SERVICE_STATE_INITIALIZED, /**< The service is initialized */
- SERVICE_STATE_CREATED, /**< The service is created. */
- SERVICE_STATE_RUNNING, /**< The service is running. */
- SERVICE_STATE_DESTROYED, /**< The service is destroyed. */
- } service_state_e;
+ typedef void *service_h;
/**
* @brief Called when the service starts.
* otherwise a negative error value
* @retval #SERVICE_ERROR_NONE Successful
* @retval #SERVICE_ERROR_INVALID_PARAMETER Invalid parameter
- * @retval #SERVICE_ERROR_INVALID_CONTEXT Invalid context
-- * @see service_create()
- * @see service_quit()
- * @see service_create_cb()
*
* @code
#include <service.h>
extern "C" service_h UNITED_SERVICE_INIT(const char* name) {
LOGD("UNITED_SERVICE_INIT. name=%s", name);
+ __name = strdup(name);
// ...
-
- service_run(service);
- __service = service;
return service;
}
-extern "C" void UNITED_SERVICE_SHUTDOWN(void) {
+
++extern "C" void UNITED_SERVICE_SHUTDOWN(const char* name) {
+ LOGD("UNITED_SERVICE_SHUTDOWN");
+ service_unregister(__name);
+ free(__name);
+ __name = nullptr;
+ }
* @endcode
*/
- int service_run(service_h service);
+ int service_unregister(const char *name);
/**
* @brief Exits the service instance.
* @retval #SERVICE_ERROR_NONE Successful
* @retval #SERVICE_ERROR_INVALID_PARAMETER Invalid parameter
* @retval #SERVICE_ERROR_INVALID_CONTEXT Invalid context
-- * @see service_create()
* @see service_run()
* @see service_destroy_cb()
*
* @retval #SERVICE_ERROR_NONE Successful
* @retval #SERVICE_ERROR_INVALID_PARAMETER Invalid parameter
* @retval #SERVICE_ERROR_OUT_OF_MEMORY Out of memory
-- * @see service_create()
*
* @code
#include <service.h>
constexpr const char kPathUnitedService[] = "/usr/share/united-service/";
constexpr const char kConf[] = "/conf/";
- bool compare_context(const std::shared_ptr<tizen_base::ServiceContext>& context1,
- const std::shared_ptr<tizen_base::ServiceContext>& context2) {
- return context1->GetPriority() > context2->GetPriority();
++bool compare_priority(const std::pair<std::string, unsigned int>& pair1,
++ const std::pair<std::string, unsigned int>& pair2) {
++ return pair1.second > pair2.second;
+}
+
- void PrintState(const std::shared_ptr<tizen_base::ServiceContext>& context) {
- switch(context->GetService()->GetState()) {
++std::string GetServiceState(tizen_base::Service::State state) {
++ switch(state) {
+ case tizen_base::Service::State::Initialized:
- _W("%s : state Initialized", context->GetService()->GetName().c_str());
- break;
++ return std::string("Initialized");
+ case tizen_base::Service::State::Created:
- _W("%s : state Created", context->GetService()->GetName().c_str());
- break;
++ return std::string("Created");
+ case tizen_base::Service::State::Running:
- _W("%s : state Running", context->GetService()->GetName().c_str());
- break;
++ return std::string("Running");
+ case tizen_base::Service::State::Destroyed:
- _W("%s : state Destroyed", context->GetService()->GetName().c_str());
- break;
- default:
- _W("invalid state");
- break;
++ return std::string("Destroyed");
+ }
++ return "";
+}
+
} // namespace
namespace tizen_base {
auto dictionary = IniParser::Parse(file.string());
auto info =
std::make_shared<ServiceInfo>(file.string(), std::move(dictionary));
- auto context = std::make_shared<ServiceContext>(std::move(info));
- // context->Init();
- contexts_.push_back(std::move(context));
++
++ orders_.push_back(std::make_pair(info->GetName(), info->GetPriority()));
+ infos_[info->GetName()] = std::move(info);
}
}
}
- if (!contexts_.empty())
- std::sort(contexts_.begin(), contexts_.end(), compare_context);
- }
-
- void ServiceLoader::RunServices() {
- unsigned int previous_priority = 0;
- std::shared_ptr<ServiceContext> previous_service = nullptr;
-
- for (auto& context : contexts_) {
- if (context->GetServiceInfo()->GetMode().compare("on-demand") == 0) {
- _W("%s is on-demand mode. it's skipped to run", context->GetName().c_str());
- continue;
- }
-
- if (previous_priority == 0)
- previous_priority = context->GetPriority();
-
- if (previous_priority == context->GetPriority()) {
- _E("@@ Priority : %d, pre-priority : %d, name : %s", context->GetPriority(), previous_priority, context->GetName().c_str());
- context->Run();
-
- PrintState(context);
-
- previous_service = context;
- } else {
- _E("@@ Priority : %d, pre-priority : %d, name : %s", context->GetPriority(), previous_priority, context->GetName().c_str());
- previous_service->GetService()->WaitRun();
-
- _E("@@ Previous state");
- PrintState(previous_service);
-
- context->Run();
-
- _E("@@ Current state");
- PrintState(context);
-
- previous_service = context;
- previous_priority = context->GetPriority();
+ for (auto& [name, info] : infos_) {
+ try {
+ auto assembly = info->GetAssembly();
+ if (!assembly->IsLoaded()) {
+ assembly->Load();
+ assembly->ModuleInit(info->GetName());
+ }
+ } catch (const Exception& e) {
+ _E("Error=%s", e.what());
+ THROW(e.GetErrorCode());
}
}
- // throw new std::runtime_error("Failed to Run service");
+
++ if (!orders_.empty())
++ std::sort(orders_.begin(), orders_.end(), compare_priority);
}
int ServiceLoader::Run() {
tizen_core_channel_object_destroy(object);
if (ret != TIZEN_CORE_ERROR_NONE) {
_E("tizen_core_channel_send() is failed. error=%d", ret);
- throw new std::runtime_error("Failed to send message");
+ THROW(SERVICE_ERROR_IO_ERROR);
+ }
+ }
+
+ void ServiceLoader::RunService(const std::string& name) {
+ auto service = GetService(name);
+ if (service != nullptr && service->IsRunning()) {
+ _E("Already running. name=%s", name.c_str());
+ THROW(SERVICE_ERROR_ALREADY_RUNNING);
+ }
+
+ auto info = GetServiceInfo(name);
+ if (info == nullptr) {
+ _E("No such service. name=%s", name.c_str());
+ THROW(SERVICE_ERROR_NO_SUCH_SERVICE);
+ }
+
+ auto listener = ServiceManager::GetInst().Get(name);
+ if (listener == nullptr) {
+ _E("No such event listener. name=%s", name.c_str());
+ THROW(SERVICE_ERROR_INVALID_CONTEXT);
+ }
+
+ service = std::make_shared<Service>(std::move(info), std::move(listener));
+ if (service == nullptr) {
+ _E("Out of memory. name=%s", name.c_str());
+ THROW(SERVICE_ERROR_OUT_OF_MEMORY);
+ }
+
+ service->SetStateChangedCb(std::bind(&ServiceLoader::ServiceStateChangedCb,
+ this, std::placeholders::_1,
+ std::placeholders::_2));
+ services_[name] = service;
+ service->Run();
+ }
+
+ void ServiceLoader::RunAllServices() {
- for (auto& [name, _] : infos_) {
++ for (auto& order : orders_) {
+ try {
- RunService(name);
++ _E("Run service : %s, priority : %d", order.first.c_str(), order.second);
++
++ auto info = GetServiceInfo(order.first);
++ if (info->GetMode() == "on-demand") {
++ _E("%s is on-demand mode. skip to run", order.first.c_str());
++ continue;
++ }
++
++ RunService(order.first);
++
++ auto service = GetService(order.first);
++
++ _E("[%s] service state is %s", order.first.c_str(), GetServiceState(service->GetState()).c_str());
+ } catch (const Exception& e) {
+ _E("Error=%s", e.what());
+ }
+ }
+ }
+
+ void ServiceLoader::QuitService(const std::string& name) {
+ auto service = GetService(name);
+ if (service == nullptr || !service->IsRunning()) {
+ _E("Not running. name=%s", name.c_str());
+ THROW(SERVICE_ERROR_INVALID_CONTEXT);
+ }
+
+ service->Quit();
+ }
+
+ void ServiceLoader::QuitAllServices() {
+ for (auto& [name, service] : services_) {
+ if (service->IsRunning()) service->Quit();
+ }
+ }
+
+ void ServiceLoader::LoadService(const std::string& name) {
+ auto found = infos_.find(name);
+ if (found == infos_.end()) THROW(SERVICE_ERROR_INVALID_PARAMETER);
+
+ auto& info = found->second;
+ auto assembly = info->GetAssembly();
+ if (assembly->IsLoaded()) THROW(SERVICE_ERROR_INVALID_CONTEXT);
+
+ try {
+ assembly->Load();
+ assembly->ModuleInit(info->GetName());
+ } catch (const Exception& e) {
+ _E("Error=%s", e.what());
+ THROW(e.GetErrorCode());
+ }
+ }
+
+ void ServiceLoader::UnloadService(const std::string& name) {
+ auto found = infos_.find(name);
+ if (found == infos_.end()) THROW(SERVICE_ERROR_NO_SUCH_SERVICE);
+
+ auto& info = found->second;
+ auto assembly = info->GetAssembly();
+ if (!assembly->IsLoaded()) THROW(SERVICE_ERROR_INVALID_CONTEXT);
+
+ try {
+ assembly->ModuleShutdown(name.c_str());
+ assembly->Unload();
+ } catch (const Exception& e) {
+ _E("Error=%s", e.what());
}
}
tizen_base::Bundle(data, false, true));
}
+ std::shared_ptr<ServiceInfo> ServiceLoader::GetServiceInfo(
+ const std::string& name) {
+ auto found = infos_.find(name);
+ if (found == infos_.end()) return nullptr;
+
+ return found->second;
+ }
+
+ std::shared_ptr<Service> ServiceLoader::GetService(const std::string& name) {
+ auto found = services_.find(name);
+ if (found == services_.end()) return nullptr;
+
+ return found->second;
+ }
+
+ void ServiceLoader::ServiceStateChangedCb(const Service* service,
+ Service::State state) {
++ _W("ServiceStateChangedCb %s, state : %s", service->GetName().c_str(), GetServiceState(state).c_str());
++
+ OnServiceStateChanged(service, state);
+ if (state == Service::State::Destroyed) {
+ services_.erase(service->GetName());
+ }
+ }
+
} // namespace tizen_base