SET(TARGET_RPC_PORT_UNITTESTS "rpc-port_unittests")
SET(TARGET_RPC_PORT_UTIL "rpc-port-util")
SET(TARGET_BENCHMARK_SERVER "rpc-port-benchmark-server")
+SET(TARGET_BENCHMARK_SERVER_DBUS "rpc-port-benchmark-server-dbus")
SET(TARGET_BENCHMARK_TOOL "rpc-port-benchmark-tool")
ENABLE_TESTING()
+++ /dev/null
-/*
- * Generated by tidlc 2.0.4.
- */
-
-#include <stdlib.h>
-#include <assert.h>
-#include <libgen.h>
-#include <dlog.h>
-
-#include "BenchmarkStub.h"
-
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#define LOG_TAG "RPC_PORT_STUB"
-
-#ifdef _E
-#undef _E
-#endif
-
-#ifdef _W
-#undef _W
-#endif
-
-#ifdef _I
-#undef _I
-#endif
-
-#ifdef _D
-#undef _D
-#endif
-
-#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
-
-#ifndef TIDL_VERSION
-#define TIDL_VERSION "2.0.4"
-#endif
-
-namespace rpc_port {
-namespace BenchmarkStub {
-
-namespace stub {
-
-Benchmark::ServiceBase::ServiceBase(std::string sender, std::string instance)
- : sender_(std::move(sender)), instance_(std::move(instance)),
- active_object_(new ActiveObject()) {}
-
-void Benchmark::ServiceBase::SetPort(rpc_port_h port) {
- port_ = port;
-}
-
-void Benchmark::ServiceBase::Disconnect() {
- int ret = rpc_port_disconnect(port_);
- if (ret == RPC_PORT_ERROR_NONE) {
- _E("Failed to disconnect the port(%d)", ret);
- return;
- }
-
- port_ = nullptr;
-}
-
-
-std::atomic<int> Benchmark::CallbackBase::seq_num_ { 0 };
-
-Benchmark::CallbackBase::CallbackBase(int delegate_id, bool once)
- : id_(delegate_id), once_(once) {
- seq_id_ = seq_num_++;
-}
-
-int Benchmark::CallbackBase::GetId() const {
- return id_;
-}
-
-int Benchmark::CallbackBase::GetSeqId() const {
- return seq_id_;
-}
-
-bool Benchmark::CallbackBase::IsOnce() const {
- return once_;
-}
-
-std::string Benchmark::CallbackBase::GetTag() const {
- return std::to_string(id_) + "::" + std::to_string(seq_id_);
-}
-
-rpc_port_parcel_h operator << (rpc_port_parcel_h h, const Benchmark::CallbackBase& cb) {
- rpc_port_parcel_write_int32(h, cb.id_);
- rpc_port_parcel_write_int32(h, cb.seq_id_);
- rpc_port_parcel_write_bool(h, cb.once_);
-
- return h;
-}
-
-rpc_port_parcel_h operator >> (rpc_port_parcel_h h, Benchmark::CallbackBase& cb) {
- rpc_port_parcel_read_int32(h, &cb.id_);
- rpc_port_parcel_read_int32(h, &cb.seq_id_);
- rpc_port_parcel_read_bool(h, &cb.once_);
-
- return h;
-}
-
-Benchmark::Benchmark() {
- int r = rpc_port_stub_create(&stub_, "Benchmark");
- if (r != RPC_PORT_ERROR_NONE) {
- _E("Failed to create stub handle");
- throw InvalidIOException();
- }
- rpc_port_stub_add_connected_event_cb(stub_, OnConnectedCB, this);
- rpc_port_stub_add_disconnected_event_cb(stub_, OnDisconnectedCB, this);
- rpc_port_stub_add_received_event_cb(stub_, OnReceivedCB, this);
-}
-
-Benchmark::~Benchmark() {
- for (auto& i : services_) {
- i->OnTerminate();
- }
-
- if (stub_) {
- rpc_port_stub_destroy(stub_);
- }
-}
-
-void Benchmark::Listen(std::shared_ptr<Benchmark::ServiceBase::Factory> service_factory) {
- service_factory_ = std::move(service_factory);
- int r = rpc_port_stub_listen(stub_);
- if (r != RPC_PORT_ERROR_NONE) {
- _E("Failed to listen stub");
- switch (r) {
- case RPC_PORT_ERROR_INVALID_PARAMETER:
- case RPC_PORT_ERROR_IO_ERROR:
- throw InvalidIOException();
- }
- }
-}
-
-void Benchmark::OnConnectedCB(const char* sender, const char* instance, void* data) {
- Benchmark* stub = static_cast<Benchmark*>(data);
- auto s = stub->service_factory_->CreateService(sender, instance);
-
- rpc_port_h port;
- int ret = rpc_port_stub_get_port(stub->stub_, RPC_PORT_PORT_CALLBACK, instance, &port);
- if (ret != RPC_PORT_ERROR_NONE) {
- _E("Failed to get the port(%d)", ret);
- return;
- }
-
- s->SetPort(port);
- s->OnCreate();
- stub->services_.emplace_back(std::move(s));
-}
-
-void Benchmark::OnDisconnectedCB(const char* sender, const char* instance, void *data) {
- Benchmark* stub = static_cast<Benchmark*>(data);
-
- for (auto& i : stub->services_) {
- if (i->GetInstance() == instance) {
- i->OnTerminate();
- stub->services_.remove(i);
- return;
- }
- }
-}
-
-int Benchmark::OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void *data)
-{
- auto* cxt = static_cast<Benchmark*>(data);
- rpc_port_parcel_h p;
- rpc_port_parcel_h result;
- rpc_port_parcel_header_h header;
- int seq_num = -1;
- int cmd;
- int ret;
- std::shared_ptr<ServiceBase> b;
- rpc_port_h callback_port;
-
- for (auto& i : cxt->services_) {
- if (i->GetInstance() == instance) {
- b = i;
- break;
- }
- }
-
- if (b.get() == nullptr) {
- _E("Failed to find Benchmark context(%s)", instance);
- return -1;
- }
-
- ret = rpc_port_stub_get_port(cxt->stub_, RPC_PORT_PORT_CALLBACK, instance,
- &callback_port);
- if (ret != 0) {
- _E("Failed to get callback port");
- }
-
- ret = rpc_port_parcel_create_from_port(&p, port);
- if (ret != 0) {
- _E("Failed to create parcel from port");
- return ret;
- }
-
- rpc_port_parcel_get_header(p, &header);
- rpc_port_parcel_header_get_seq_num(header, &seq_num);
-
- rpc_port_parcel_create(&result);
- rpc_port_parcel_get_header(result, &header);
- rpc_port_parcel_header_set_tag(header, TIDL_VERSION);
- rpc_port_parcel_header_set_seq_num(header, seq_num);
-
- rpc_port_parcel_read_int32(p, &cmd);
-
- switch (cmd) {
- case static_cast<int>(MethodId::Test): {
- char* param1_raw = nullptr;
- rpc_port_parcel_read_string(p, ¶m1_raw);
- std::string param1(param1_raw);
- free(param1_raw);
- auto retVal = b->Test(std::move(param1));
- rpc_port_parcel_write_int32(result, static_cast<int>(MethodId::__Result));
- rpc_port_parcel_write_int32(result, retVal);
- rpc_port_parcel_send(result, port);
- break;
- }
-
- default:
- _E("Unknown command(%d)", cmd);
- rpc_port_parcel_destroy(p);
- rpc_port_parcel_destroy(result);
- return -1;
- }
-
- rpc_port_parcel_destroy(p);
- rpc_port_parcel_destroy(result);
-
- return ret;
-}
-
-} // namespace stub
-} // namespace BenchmarkStub
-} // namespace rpc_port
+++ /dev/null
-/*
- * Generated by tidlc 2.0.4.
- */
-
-#pragma once
-
-#include <bundle.h>
-#include <rpc-port-parcel.h>
-#include <rpc-port.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-#include <list>
-#include <atomic>
-#include <condition_variable>
-#include <mutex>
-#include <deque>
-#include <thread>
-
-namespace rpc_port {
-namespace BenchmarkStub {
-
-class Bundle final {
- public:
- Bundle() {
- raw_ = bundle_create();
- }
-
- Bundle(bundle* b) {
- raw_ = b;
- }
-
- ~Bundle() {
- if (raw_)
- bundle_free(raw_);
- }
-
- Bundle(Bundle&& b) : raw_(b.raw_) {
- b.raw_ = nullptr;
- }
-
- Bundle& operator = (Bundle&& b) {
- if (this != &b) {
- if (raw_)
- bundle_free(raw_);
-
- raw_ = b.raw_;
- b.raw_ = nullptr;
- }
- return *this;
- }
-
- Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
-
- Bundle& operator = (const Bundle& b) {
- if (this != &b) {
- if (raw_)
- bundle_free(raw_);
-
- raw_ = bundle_dup(b.GetHandle());
- }
- return *this;
- }
-
- bundle* GetHandle() const {
- return raw_;
- }
-
- private:
- bundle* raw_;
-};
-
-class File final {
- public:
- File() {
- }
-
- File(std::string filename) {
- filename_ = filename;
- }
-
- std::string GetFileName() const {
- return filename_;
- }
-
- private:
- std::string filename_;
-};
-
-namespace stub {
-
-class Exception {};
-class NotConnectedSocketException : public Exception {};
-class InvalidProtocolException : public Exception {};
-class InvalidIOException : public Exception {};
-class InvalidCallbackException : public Exception {};
-class Job {
- public:
- class IEvent {
- public:
- virtual ~IEvent() = default;
- virtual void Run() = 0;
- };
-
- Job() : handler_(nullptr) {
- }
-
- Job(IEvent* handler) : handler_(handler) {
- }
- virtual ~Job() = default;
-
- Job(const Job& job) {
- handler_ = job.handler_;
- }
-
- Job& operator = (const Job& job) {
- if (this != &job)
- handler_ = job.handler_;
- return *this;
- }
- Job(Job&& job) noexcept {
- handler_ = job.handler_;
- job.handler_ = nullptr;
- }
-
- Job& operator = (Job&& job) noexcept {
- if (this != &job) {
- handler_ = job.handler_;
- job.handler_ = nullptr;
- }
- return *this;
- }
-
- void Invoke() {
- if (handler_)
- handler_->Run();
- }
-
- private:
- IEvent* handler_;
-};
-
-
-template <class T>
-class SharedQueue {
- public:
- SharedQueue() = default;
- virtual ~SharedQueue() = default;
-
- void Push(T item) {
- std::lock_guard<std::mutex> lock(mutex_);
- queue_.push_back(item);
- cond_var_.notify_one();
- }
-
- void PushFront(T item) {
- std::lock_guard<std::mutex> lock(mutex_);
- queue_.push_front(item);
- cond_var_.notify_one();
- }
-
- bool TryAndPop(T& item) {
- std::lock_guard<std::mutex> lock(mutex_);
- if (queue_.empty())
- return false;
-
- item = queue_.front();
- queue_.pop_front();
-
- return true;
- }
-
- void WaitAndPop(T& item) {
- std::unique_lock<std::mutex> lock(mutex_);
- while (queue_.empty())
- cond_var_.wait(lock);
-
- item = queue_.front();
- queue_.pop_front();
- }
-
- bool Empty() {
- std::lock_guard<std::mutex> lock(mutex_);
- return queue_.empty();
- }
-
- int Size() {
- std::lock_guard<std::mutex> lock(mutex_);
- return queue_.size();
- }
-
- private:
- std::deque<T> queue_;
- mutable std::mutex mutex_;
- std::condition_variable cond_var_;
-};
-
-class ActiveObject : public Job::IEvent {
- public:
- ActiveObject() {
- thread_ = std::thread([&]{
- do {
- std::shared_ptr<Job> item;
- queue_.WaitAndPop(item);
- item->Invoke();
- } while (!done_);
- });
- }
- virtual ~ActiveObject() {
- Quit();
- thread_.join();
- }
-
- public:
- void Send(std::shared_ptr<Job> job) {
- queue_.Push(std::move(job));
- }
-
- private:
- void Quit() {
- Send(std::shared_ptr<Job>(new (std::nothrow) Job(this)));
- }
- void Run() override {
- done_ = true;
- }
-
- private:
- std::thread thread_;
- bool done_ = false;
- SharedQueue<std::shared_ptr<Job>> queue_;
-};
-
-
-class Benchmark final {
- public:
- class ServiceBase;
-
- class CallbackBase {
- public:
- CallbackBase(int delegate_id, bool once);
- virtual ~CallbackBase() = default;
-
- int GetId() const;
- int GetSeqId() const;
- bool IsOnce() const;
- std::string GetTag() const;
-
- private:
- friend rpc_port_parcel_h operator << (rpc_port_parcel_h h, const CallbackBase& cb);
- friend rpc_port_parcel_h operator >> (rpc_port_parcel_h h, CallbackBase& cb);
-
- static std::atomic<int> seq_num_;
- int id_;
- int seq_id_;
- bool once_;
- };
-
- class ServiceBase {
- public:
- class Factory {
- public:
- virtual ~Factory() = default;
-
- /// <summary>
- /// The method for making service instances
- /// </summary>
- /// <param name="sender">The client app ID</param>
- /// <param name="instance">The client instance ID</param>
- virtual std::unique_ptr<ServiceBase> CreateService(std::string sender, std::string instance) = 0;
- };
-
- virtual ~ServiceBase() = default;
-
- /// <summary>
- /// Gets client app ID
- /// </summary>
- const std::string& GetSender() const {
- return sender_;
- }
-
- /// <summary>
- /// Gets client instance ID
- /// </summary>
- const std::string& GetInstance() const {
- return instance_;
- }
-
- /// <summary>
- /// Sets the client app port
- /// </summary>
- /// <param name="port">The port of the client</param>
- void SetPort(rpc_port_h port);
-
- /// <summary>
- /// Disconnects from the client app
- /// </summary>
- /// <exception cref="InvalidIOException">
- /// Thrown when internal I/O error happen.
- /// </exception>
- void Disconnect();
-
- /// <summary>
- /// This method will be called when the client is connected
- /// </summary>
- virtual void OnCreate() = 0;
-
- /// <summary>
- /// This method will be called when the client is disconnected
- /// </summary>
- virtual void OnTerminate() = 0;
-
- void Dispatch(rpc_port_h port, rpc_port_h callback_port,
- rpc_port_parcel_h parcel, std::shared_ptr<ServiceBase> service);
-
- virtual int Test(std::string data) = 0;
-
- protected:
- ServiceBase(std::string sender, std::string instance);
-
- private:
- std::string sender_;
- std::string instance_;
- rpc_port_h port_ = nullptr;
- std::unique_ptr<ActiveObject> active_object_;
- };
-
- Benchmark();
- ~Benchmark();
-
- /// <summary>
- /// Listens to client apps
- /// </summary>
- /// <param name="service_factory">The factory object for making service instances</param>
- /// <exception cref="InvalidIOException">
- /// Thrown when internal I/O error happen.
- /// </exception>
- void Listen(std::shared_ptr<ServiceBase::Factory> service_factory);
-
- /// <summary>
- /// Gets service objects which are connected
- /// </summary>
- /// <returns>The list of service objects which are connected</returns>
- const std::list<std::shared_ptr<ServiceBase>>& GetServices() const {
- return services_;
- }
-
- private:
- enum class MethodId : int {
- __Result = 0,
- __Callback = 1,
- Test = 2,
-
- };
-
- enum class DelegateId : int {
-
- };
- static void OnConnectedCB(const char* sender, const char* instance, void* data);
- static void OnDisconnectedCB(const char* sender, const char* instance, void* data);
- static int OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void* data);
-
- rpc_port_stub_h stub_ = nullptr;
- std::shared_ptr<ServiceBase::Factory> service_factory_;
- std::list<std::shared_ptr<ServiceBase>> services_;
-};
-} // namespace stub
-} // namespace BenchmarkStub
-} // namespace rpc_port
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} BENCHMARK_SERVER_SRCS)
-
-ADD_EXECUTABLE(${TARGET_BENCHMARK_SERVER} ${BENCHMARK_SERVER_SRCS})
-
-TARGET_INCLUDE_DIRECTORIES(${TARGET_BENCHMARK_SERVER} PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/../../include/)
-
-APPLY_PKG_CONFIG(${TARGET_BENCHMARK_SERVER} PUBLIC
- AUL_DEPS
- DLOG_DEPS
- GLIB_DEPS
-)
-
-TARGET_LINK_LIBRARIES(${TARGET_BENCHMARK_SERVER} PUBLIC
- ${TARGET_RPC_PORT} "-lpthread")
-SET_TARGET_PROPERTIES(${TARGET_BENCHMARK_SERVER} PROPERTIES
- COMPILE_FLAGS "-fPIE")
-SET_TARGET_PROPERTIES(${TARGET_BENCHMARK_SERVER} PROPERTIES
- LINK_FLAGS "-pie")
-
-INSTALL(TARGETS ${TARGET_BENCHMARK_SERVER} DESTINATION bin)
+ADD_SUBDIRECTORY(tidl)
+ADD_SUBDIRECTORY(dbus)
--- /dev/null
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} BENCHMARK_SERVER_DBUS_SRCS)
+
+ADD_EXECUTABLE(${TARGET_BENCHMARK_SERVER_DBUS} ${BENCHMARK_SERVER_DBUS_SRCS})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_BENCHMARK_SERVER_DBUS} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/)
+
+APPLY_PKG_CONFIG(${TARGET_BENCHMARK_SERVER_DBUS} PUBLIC
+ DLOG_DEPS
+ GLIB_DEPS
+ GIO_DEPS
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_BENCHMARK_SERVER_DBUS} PUBLIC
+ ${TARGET_RPC_PORT} "-lpthread")
+SET_TARGET_PROPERTIES(${TARGET_BENCHMARK_SERVER_DBUS} PROPERTIES
+ COMPILE_FLAGS "-fPIE")
+SET_TARGET_PROPERTIES(${TARGET_BENCHMARK_SERVER_DBUS} PROPERTIES
+ LINK_FLAGS "-pie")
+
+INSTALL(TARGETS ${TARGET_BENCHMARK_SERVER_DBUS} DESTINATION bin)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/rpc-port-benchmark.conf DESTINATION /etc/dbus-1/system.d)
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LOG_PRIVATE_HH_
+#define LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "RPC_PORT_BENCHMARK_SERVER_DBUS"
+
+#undef _E
+#define _E LOGE
+
+#undef _W
+#define _W LOGW
+
+#undef _I
+#define _I LOGI
+
+#undef _D
+#define _D LOGD
+
+#endif // LOG_PRIVATE_HH_
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <string_view>
+#include <string>
+
+#include "log-private.hh"
+
+namespace {
+
+constexpr const char BUS_NAME[] = "tizen.appfw.rpcport.benchmark.dbus";
+constexpr const char OBJECT_PATH[] = "/tizen/appfw/rpcport/benchmark/dbus";
+
+constexpr const char INTROSPECTION_XML[] = R"__dbus(
+<node>
+ <interface name='tizen.appfw.rpcport.benchmark.dbus'>
+ <method name='Test'>
+ <arg type='s' name='data' direction='in'/>
+ <arg type='i' name='ret' direction='out'/>
+ </method>
+ </interface>
+</node>
+)__dbus";
+
+class MainLoop {
+ public:
+ MainLoop() {
+ loop_ = g_main_loop_new(nullptr, FALSE);
+ }
+
+ ~MainLoop() {
+ g_main_loop_unref(loop_);
+ if (introspection_data_)
+ g_dbus_node_info_unref(introspection_data_);
+ }
+
+ int OnTest(std::string data) {
+ return 0;
+ }
+
+ void OnBusAcquired(GDBusConnection* connection, const gchar* name) {
+ _I("bus acquired(%s)", name);
+
+ static const GDBusInterfaceVTable interface_vtable = {
+ [](GDBusConnection *connection,
+ const gchar *sender, const gchar *object_path,
+ const gchar *interface_name, const gchar *method_name,
+ GVariant *parameters, GDBusMethodInvocation *invocation,
+ gpointer user_data) {
+ if (std::string_view(method_name) == "Test") {
+ char* data = nullptr;
+ g_variant_get(parameters, "(&s)", &data);
+ auto* obj = static_cast<MainLoop*>(user_data);
+ int ret = obj->OnTest(data);
+
+ GVariant* param = g_variant_new("(i)", ret);
+ g_dbus_method_invocation_return_value(invocation, param);
+ }
+ },
+ nullptr,
+ nullptr
+ };
+
+ GError* error = nullptr;
+ guint reg_id = g_dbus_connection_register_object(connection,
+ OBJECT_PATH,
+ introspection_data_->interfaces[0],
+ &interface_vtable,
+ this, nullptr, &error);
+ if (reg_id == 0) {
+ _E("g_dbus_connection_register_object error(%s)", error ? error->message : "");
+ g_error_free(error);
+ }
+ }
+
+ void Run() {
+ GError* error = nullptr;
+ introspection_data_ = g_dbus_node_info_new_for_xml(INTROSPECTION_XML,
+ &error);
+ if (!introspection_data_) {
+ _E("g_dbus_node_info_new_for_xml error(%s)", error ? error->message : "");
+ g_error_free(error);
+ return;
+ }
+
+ guint owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+ BUS_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ [](GDBusConnection* connection, const gchar* name,
+ gpointer user_data) {
+ auto* obj = static_cast<MainLoop*>(user_data);
+ obj->OnBusAcquired(connection, name);
+ },
+ [](GDBusConnection* connection,
+ const gchar* name, gpointer user_data) {
+ _I("name acquired(%s)", name);
+ },
+ [](GDBusConnection* connection,
+ const gchar* name, gpointer user_data) {
+ _I("name lost(%s)", name);
+ },
+ this, nullptr);
+ if (!owner_id) {
+ _E("g_bus_own_name error");
+ g_dbus_node_info_unref(introspection_data_);
+ return;
+ }
+
+ g_main_loop_run(loop_);
+ }
+
+ void Quit() {
+ g_main_loop_quit(loop_);
+ }
+
+ private:
+ GMainLoop* loop_ = nullptr;
+ GDBusNodeInfo* introspection_data_ = nullptr;
+};
+
+} // namespace
+
+int main(int argc, char** argv) {
+ MainLoop loop;
+ loop.Run();
+ return 0;
+}
--- /dev/null
+<!DOCTYPE busconfig PUBLIC
+"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<busconfig>
+ <policy context="default">
+ <allow own="tizen.appfw.rpcport.benchmark.dbus" />
+ <allow send_destination="tizen.appfw.rpcport.benchmark.dbus"
+ send_interface="tizen.appfw.rpcport.benchmark.dbus" send_type="method_call" />
+ </policy>
+</busconfig>
+++ /dev/null
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LOG_PRIVATE_HH_
-#define LOG_PRIVATE_HH_
-
-#include <dlog.h>
-
-#undef LOG_TAG
-#define LOG_TAG "RPC_PORT_BENCHMARK_SERVER"
-
-#undef _E
-#define _E LOGE
-
-#undef _W
-#define _W LOGW
-
-#undef _I
-#define _I LOGI
-
-#undef _D
-#define _D LOGD
-
-#endif // LOG_PRIVATE_HH_
+++ /dev/null
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <glib.h>
-
-#include <aul_proc.h>
-
-#include "BenchmarkStub.h"
-#include "log-private.hh"
-
-namespace {
-constexpr const char SERVER_PROC_NAME[] = "org.tizen.appfw.rpc_port.benchmark";
-
-namespace bs = rpc_port::BenchmarkStub::stub;
-
-class TestService : public bs::Benchmark::ServiceBase {
- public:
- class Factory : public bs::Benchmark::ServiceBase::Factory {
- public:
- virtual ~Factory() = default;
-
- std::unique_ptr<bs::Benchmark::ServiceBase>
- CreateService(std::string sender, std::string instance) {
- return std::unique_ptr<bs::Benchmark::ServiceBase>(
- new TestService(std::move(sender), std::move(instance)));
- }
- };
-
- TestService(std::string sender, std::string instance) :
- bs::Benchmark::ServiceBase(std::move(sender), std::move(instance)) {}
-
- virtual ~TestService() = default;
-
- void OnCreate() override {
- }
-
- void OnTerminate() override {
- }
-
- int Test(std::string data) override {
- return 0;
- }
-};
-
-class MainLoop {
- public:
- MainLoop() {
- loop_ = g_main_loop_new(nullptr, FALSE);
- }
-
- ~MainLoop() {
- g_main_loop_unref(loop_);
- }
-
- void Run() {
- int ret = aul_proc_register(SERVER_PROC_NAME, nullptr);
- if (ret != AUL_R_OK) {
- _E("aul_proc_register() failed (%d)", ret);
- return;
- }
-
- try {
- stub_.Listen(std::shared_ptr<bs::Benchmark::ServiceBase::Factory>(
- new TestService::Factory()));
- } catch (const bs::Exception&) {
- _E("stub listen is failed");
- }
-
- g_main_loop_run(loop_);
- }
-
- void Quit() {
- g_main_loop_quit(loop_);
- }
-
- private:
- GMainLoop* loop_;
- bs::Benchmark stub_;
-};
-
-} // namespace
-
-int main(int argc, char** argv) {
- MainLoop loop;
- loop.Run();
- return 0;
-}
--- /dev/null
+/*
+ * Generated by tidlc 2.0.4.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <libgen.h>
+#include <dlog.h>
+
+#include "BenchmarkStub.h"
+
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "RPC_PORT_STUB"
+
+#ifdef _E
+#undef _E
+#endif
+
+#ifdef _W
+#undef _W
+#endif
+
+#ifdef _I
+#undef _I
+#endif
+
+#ifdef _D
+#undef _D
+#endif
+
+#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#ifndef TIDL_VERSION
+#define TIDL_VERSION "2.0.4"
+#endif
+
+namespace rpc_port {
+namespace BenchmarkStub {
+
+namespace stub {
+
+Benchmark::ServiceBase::ServiceBase(std::string sender, std::string instance)
+ : sender_(std::move(sender)), instance_(std::move(instance)),
+ active_object_(new ActiveObject()) {}
+
+void Benchmark::ServiceBase::SetPort(rpc_port_h port) {
+ port_ = port;
+}
+
+void Benchmark::ServiceBase::Disconnect() {
+ int ret = rpc_port_disconnect(port_);
+ if (ret == RPC_PORT_ERROR_NONE) {
+ _E("Failed to disconnect the port(%d)", ret);
+ return;
+ }
+
+ port_ = nullptr;
+}
+
+
+std::atomic<int> Benchmark::CallbackBase::seq_num_ { 0 };
+
+Benchmark::CallbackBase::CallbackBase(int delegate_id, bool once)
+ : id_(delegate_id), once_(once) {
+ seq_id_ = seq_num_++;
+}
+
+int Benchmark::CallbackBase::GetId() const {
+ return id_;
+}
+
+int Benchmark::CallbackBase::GetSeqId() const {
+ return seq_id_;
+}
+
+bool Benchmark::CallbackBase::IsOnce() const {
+ return once_;
+}
+
+std::string Benchmark::CallbackBase::GetTag() const {
+ return std::to_string(id_) + "::" + std::to_string(seq_id_);
+}
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const Benchmark::CallbackBase& cb) {
+ rpc_port_parcel_write_int32(h, cb.id_);
+ rpc_port_parcel_write_int32(h, cb.seq_id_);
+ rpc_port_parcel_write_bool(h, cb.once_);
+
+ return h;
+}
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, Benchmark::CallbackBase& cb) {
+ rpc_port_parcel_read_int32(h, &cb.id_);
+ rpc_port_parcel_read_int32(h, &cb.seq_id_);
+ rpc_port_parcel_read_bool(h, &cb.once_);
+
+ return h;
+}
+
+Benchmark::Benchmark() {
+ int r = rpc_port_stub_create(&stub_, "Benchmark");
+ if (r != RPC_PORT_ERROR_NONE) {
+ _E("Failed to create stub handle");
+ throw InvalidIOException();
+ }
+ rpc_port_stub_add_connected_event_cb(stub_, OnConnectedCB, this);
+ rpc_port_stub_add_disconnected_event_cb(stub_, OnDisconnectedCB, this);
+ rpc_port_stub_add_received_event_cb(stub_, OnReceivedCB, this);
+}
+
+Benchmark::~Benchmark() {
+ for (auto& i : services_) {
+ i->OnTerminate();
+ }
+
+ if (stub_) {
+ rpc_port_stub_destroy(stub_);
+ }
+}
+
+void Benchmark::Listen(std::shared_ptr<Benchmark::ServiceBase::Factory> service_factory) {
+ service_factory_ = std::move(service_factory);
+ int r = rpc_port_stub_listen(stub_);
+ if (r != RPC_PORT_ERROR_NONE) {
+ _E("Failed to listen stub");
+ switch (r) {
+ case RPC_PORT_ERROR_INVALID_PARAMETER:
+ case RPC_PORT_ERROR_IO_ERROR:
+ throw InvalidIOException();
+ }
+ }
+}
+
+void Benchmark::OnConnectedCB(const char* sender, const char* instance, void* data) {
+ Benchmark* stub = static_cast<Benchmark*>(data);
+ auto s = stub->service_factory_->CreateService(sender, instance);
+
+ rpc_port_h port;
+ int ret = rpc_port_stub_get_port(stub->stub_, RPC_PORT_PORT_CALLBACK, instance, &port);
+ if (ret != RPC_PORT_ERROR_NONE) {
+ _E("Failed to get the port(%d)", ret);
+ return;
+ }
+
+ s->SetPort(port);
+ s->OnCreate();
+ stub->services_.emplace_back(std::move(s));
+}
+
+void Benchmark::OnDisconnectedCB(const char* sender, const char* instance, void *data) {
+ Benchmark* stub = static_cast<Benchmark*>(data);
+
+ for (auto& i : stub->services_) {
+ if (i->GetInstance() == instance) {
+ i->OnTerminate();
+ stub->services_.remove(i);
+ return;
+ }
+ }
+}
+
+int Benchmark::OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void *data)
+{
+ auto* cxt = static_cast<Benchmark*>(data);
+ rpc_port_parcel_h p;
+ rpc_port_parcel_h result;
+ rpc_port_parcel_header_h header;
+ int seq_num = -1;
+ int cmd;
+ int ret;
+ std::shared_ptr<ServiceBase> b;
+ rpc_port_h callback_port;
+
+ for (auto& i : cxt->services_) {
+ if (i->GetInstance() == instance) {
+ b = i;
+ break;
+ }
+ }
+
+ if (b.get() == nullptr) {
+ _E("Failed to find Benchmark context(%s)", instance);
+ return -1;
+ }
+
+ ret = rpc_port_stub_get_port(cxt->stub_, RPC_PORT_PORT_CALLBACK, instance,
+ &callback_port);
+ if (ret != 0) {
+ _E("Failed to get callback port");
+ }
+
+ ret = rpc_port_parcel_create_from_port(&p, port);
+ if (ret != 0) {
+ _E("Failed to create parcel from port");
+ return ret;
+ }
+
+ rpc_port_parcel_get_header(p, &header);
+ rpc_port_parcel_header_get_seq_num(header, &seq_num);
+
+ rpc_port_parcel_create(&result);
+ rpc_port_parcel_get_header(result, &header);
+ rpc_port_parcel_header_set_tag(header, TIDL_VERSION);
+ rpc_port_parcel_header_set_seq_num(header, seq_num);
+
+ rpc_port_parcel_read_int32(p, &cmd);
+
+ switch (cmd) {
+ case static_cast<int>(MethodId::Test): {
+ char* param1_raw = nullptr;
+ rpc_port_parcel_read_string(p, ¶m1_raw);
+ std::string param1(param1_raw);
+ free(param1_raw);
+ auto retVal = b->Test(std::move(param1));
+ rpc_port_parcel_write_int32(result, static_cast<int>(MethodId::__Result));
+ rpc_port_parcel_write_int32(result, retVal);
+ rpc_port_parcel_send(result, port);
+ break;
+ }
+
+ default:
+ _E("Unknown command(%d)", cmd);
+ rpc_port_parcel_destroy(p);
+ rpc_port_parcel_destroy(result);
+ return -1;
+ }
+
+ rpc_port_parcel_destroy(p);
+ rpc_port_parcel_destroy(result);
+
+ return ret;
+}
+
+} // namespace stub
+} // namespace BenchmarkStub
+} // namespace rpc_port
--- /dev/null
+/*
+ * Generated by tidlc 2.0.4.
+ */
+
+#pragma once
+
+#include <bundle.h>
+#include <rpc-port-parcel.h>
+#include <rpc-port.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <list>
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <deque>
+#include <thread>
+
+namespace rpc_port {
+namespace BenchmarkStub {
+
+class Bundle final {
+ public:
+ Bundle() {
+ raw_ = bundle_create();
+ }
+
+ Bundle(bundle* b) {
+ raw_ = b;
+ }
+
+ ~Bundle() {
+ if (raw_)
+ bundle_free(raw_);
+ }
+
+ Bundle(Bundle&& b) : raw_(b.raw_) {
+ b.raw_ = nullptr;
+ }
+
+ Bundle& operator = (Bundle&& b) {
+ if (this != &b) {
+ if (raw_)
+ bundle_free(raw_);
+
+ raw_ = b.raw_;
+ b.raw_ = nullptr;
+ }
+ return *this;
+ }
+
+ Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
+
+ Bundle& operator = (const Bundle& b) {
+ if (this != &b) {
+ if (raw_)
+ bundle_free(raw_);
+
+ raw_ = bundle_dup(b.GetHandle());
+ }
+ return *this;
+ }
+
+ bundle* GetHandle() const {
+ return raw_;
+ }
+
+ private:
+ bundle* raw_;
+};
+
+class File final {
+ public:
+ File() {
+ }
+
+ File(std::string filename) {
+ filename_ = filename;
+ }
+
+ std::string GetFileName() const {
+ return filename_;
+ }
+
+ private:
+ std::string filename_;
+};
+
+namespace stub {
+
+class Exception {};
+class NotConnectedSocketException : public Exception {};
+class InvalidProtocolException : public Exception {};
+class InvalidIOException : public Exception {};
+class InvalidCallbackException : public Exception {};
+class Job {
+ public:
+ class IEvent {
+ public:
+ virtual ~IEvent() = default;
+ virtual void Run() = 0;
+ };
+
+ Job() : handler_(nullptr) {
+ }
+
+ Job(IEvent* handler) : handler_(handler) {
+ }
+ virtual ~Job() = default;
+
+ Job(const Job& job) {
+ handler_ = job.handler_;
+ }
+
+ Job& operator = (const Job& job) {
+ if (this != &job)
+ handler_ = job.handler_;
+ return *this;
+ }
+ Job(Job&& job) noexcept {
+ handler_ = job.handler_;
+ job.handler_ = nullptr;
+ }
+
+ Job& operator = (Job&& job) noexcept {
+ if (this != &job) {
+ handler_ = job.handler_;
+ job.handler_ = nullptr;
+ }
+ return *this;
+ }
+
+ void Invoke() {
+ if (handler_)
+ handler_->Run();
+ }
+
+ private:
+ IEvent* handler_;
+};
+
+
+template <class T>
+class SharedQueue {
+ public:
+ SharedQueue() = default;
+ virtual ~SharedQueue() = default;
+
+ void Push(T item) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ queue_.push_back(item);
+ cond_var_.notify_one();
+ }
+
+ void PushFront(T item) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ queue_.push_front(item);
+ cond_var_.notify_one();
+ }
+
+ bool TryAndPop(T& item) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (queue_.empty())
+ return false;
+
+ item = queue_.front();
+ queue_.pop_front();
+
+ return true;
+ }
+
+ void WaitAndPop(T& item) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ while (queue_.empty())
+ cond_var_.wait(lock);
+
+ item = queue_.front();
+ queue_.pop_front();
+ }
+
+ bool Empty() {
+ std::lock_guard<std::mutex> lock(mutex_);
+ return queue_.empty();
+ }
+
+ int Size() {
+ std::lock_guard<std::mutex> lock(mutex_);
+ return queue_.size();
+ }
+
+ private:
+ std::deque<T> queue_;
+ mutable std::mutex mutex_;
+ std::condition_variable cond_var_;
+};
+
+class ActiveObject : public Job::IEvent {
+ public:
+ ActiveObject() {
+ thread_ = std::thread([&]{
+ do {
+ std::shared_ptr<Job> item;
+ queue_.WaitAndPop(item);
+ item->Invoke();
+ } while (!done_);
+ });
+ }
+ virtual ~ActiveObject() {
+ Quit();
+ thread_.join();
+ }
+
+ public:
+ void Send(std::shared_ptr<Job> job) {
+ queue_.Push(std::move(job));
+ }
+
+ private:
+ void Quit() {
+ Send(std::shared_ptr<Job>(new (std::nothrow) Job(this)));
+ }
+ void Run() override {
+ done_ = true;
+ }
+
+ private:
+ std::thread thread_;
+ bool done_ = false;
+ SharedQueue<std::shared_ptr<Job>> queue_;
+};
+
+
+class Benchmark final {
+ public:
+ class ServiceBase;
+
+ class CallbackBase {
+ public:
+ CallbackBase(int delegate_id, bool once);
+ virtual ~CallbackBase() = default;
+
+ int GetId() const;
+ int GetSeqId() const;
+ bool IsOnce() const;
+ std::string GetTag() const;
+
+ private:
+ friend rpc_port_parcel_h operator << (rpc_port_parcel_h h, const CallbackBase& cb);
+ friend rpc_port_parcel_h operator >> (rpc_port_parcel_h h, CallbackBase& cb);
+
+ static std::atomic<int> seq_num_;
+ int id_;
+ int seq_id_;
+ bool once_;
+ };
+
+ class ServiceBase {
+ public:
+ class Factory {
+ public:
+ virtual ~Factory() = default;
+
+ /// <summary>
+ /// The method for making service instances
+ /// </summary>
+ /// <param name="sender">The client app ID</param>
+ /// <param name="instance">The client instance ID</param>
+ virtual std::unique_ptr<ServiceBase> CreateService(std::string sender, std::string instance) = 0;
+ };
+
+ virtual ~ServiceBase() = default;
+
+ /// <summary>
+ /// Gets client app ID
+ /// </summary>
+ const std::string& GetSender() const {
+ return sender_;
+ }
+
+ /// <summary>
+ /// Gets client instance ID
+ /// </summary>
+ const std::string& GetInstance() const {
+ return instance_;
+ }
+
+ /// <summary>
+ /// Sets the client app port
+ /// </summary>
+ /// <param name="port">The port of the client</param>
+ void SetPort(rpc_port_h port);
+
+ /// <summary>
+ /// Disconnects from the client app
+ /// </summary>
+ /// <exception cref="InvalidIOException">
+ /// Thrown when internal I/O error happen.
+ /// </exception>
+ void Disconnect();
+
+ /// <summary>
+ /// This method will be called when the client is connected
+ /// </summary>
+ virtual void OnCreate() = 0;
+
+ /// <summary>
+ /// This method will be called when the client is disconnected
+ /// </summary>
+ virtual void OnTerminate() = 0;
+
+ void Dispatch(rpc_port_h port, rpc_port_h callback_port,
+ rpc_port_parcel_h parcel, std::shared_ptr<ServiceBase> service);
+
+ virtual int Test(std::string data) = 0;
+
+ protected:
+ ServiceBase(std::string sender, std::string instance);
+
+ private:
+ std::string sender_;
+ std::string instance_;
+ rpc_port_h port_ = nullptr;
+ std::unique_ptr<ActiveObject> active_object_;
+ };
+
+ Benchmark();
+ ~Benchmark();
+
+ /// <summary>
+ /// Listens to client apps
+ /// </summary>
+ /// <param name="service_factory">The factory object for making service instances</param>
+ /// <exception cref="InvalidIOException">
+ /// Thrown when internal I/O error happen.
+ /// </exception>
+ void Listen(std::shared_ptr<ServiceBase::Factory> service_factory);
+
+ /// <summary>
+ /// Gets service objects which are connected
+ /// </summary>
+ /// <returns>The list of service objects which are connected</returns>
+ const std::list<std::shared_ptr<ServiceBase>>& GetServices() const {
+ return services_;
+ }
+
+ private:
+ enum class MethodId : int {
+ __Result = 0,
+ __Callback = 1,
+ Test = 2,
+
+ };
+
+ enum class DelegateId : int {
+
+ };
+ static void OnConnectedCB(const char* sender, const char* instance, void* data);
+ static void OnDisconnectedCB(const char* sender, const char* instance, void* data);
+ static int OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void* data);
+
+ rpc_port_stub_h stub_ = nullptr;
+ std::shared_ptr<ServiceBase::Factory> service_factory_;
+ std::list<std::shared_ptr<ServiceBase>> services_;
+};
+} // namespace stub
+} // namespace BenchmarkStub
+} // namespace rpc_port
--- /dev/null
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} BENCHMARK_SERVER_SRCS)
+
+ADD_EXECUTABLE(${TARGET_BENCHMARK_SERVER} ${BENCHMARK_SERVER_SRCS})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_BENCHMARK_SERVER} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/)
+
+APPLY_PKG_CONFIG(${TARGET_BENCHMARK_SERVER} PUBLIC
+ AUL_DEPS
+ DLOG_DEPS
+ GLIB_DEPS
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_BENCHMARK_SERVER} PUBLIC
+ ${TARGET_RPC_PORT} "-lpthread")
+SET_TARGET_PROPERTIES(${TARGET_BENCHMARK_SERVER} PROPERTIES
+ COMPILE_FLAGS "-fPIE")
+SET_TARGET_PROPERTIES(${TARGET_BENCHMARK_SERVER} PROPERTIES
+ LINK_FLAGS "-pie")
+
+INSTALL(TARGETS ${TARGET_BENCHMARK_SERVER} DESTINATION bin)
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LOG_PRIVATE_HH_
+#define LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "RPC_PORT_BENCHMARK_SERVER"
+
+#undef _E
+#define _E LOGE
+
+#undef _W
+#define _W LOGW
+
+#undef _I
+#define _I LOGI
+
+#undef _D
+#define _D LOGD
+
+#endif // LOG_PRIVATE_HH_
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glib.h>
+
+#include <aul_proc.h>
+
+#include "BenchmarkStub.h"
+#include "log-private.hh"
+
+namespace {
+constexpr const char SERVER_PROC_NAME[] = "org.tizen.appfw.rpc_port.benchmark";
+
+namespace bs = rpc_port::BenchmarkStub::stub;
+
+class TestService : public bs::Benchmark::ServiceBase {
+ public:
+ class Factory : public bs::Benchmark::ServiceBase::Factory {
+ public:
+ virtual ~Factory() = default;
+
+ std::unique_ptr<bs::Benchmark::ServiceBase>
+ CreateService(std::string sender, std::string instance) {
+ return std::unique_ptr<bs::Benchmark::ServiceBase>(
+ new TestService(std::move(sender), std::move(instance)));
+ }
+ };
+
+ TestService(std::string sender, std::string instance) :
+ bs::Benchmark::ServiceBase(std::move(sender), std::move(instance)) {}
+
+ virtual ~TestService() = default;
+
+ void OnCreate() override {
+ }
+
+ void OnTerminate() override {
+ }
+
+ int Test(std::string data) override {
+ return 0;
+ }
+};
+
+class MainLoop {
+ public:
+ MainLoop() {
+ loop_ = g_main_loop_new(nullptr, FALSE);
+ }
+
+ ~MainLoop() {
+ g_main_loop_unref(loop_);
+ }
+
+ void Run() {
+ int ret = aul_proc_register(SERVER_PROC_NAME, nullptr);
+ if (ret != AUL_R_OK) {
+ _E("aul_proc_register() failed (%d)", ret);
+ return;
+ }
+
+ try {
+ stub_.Listen(std::shared_ptr<bs::Benchmark::ServiceBase::Factory>(
+ new TestService::Factory()));
+ } catch (const bs::Exception&) {
+ _E("stub listen is failed");
+ }
+
+ g_main_loop_run(loop_);
+ }
+
+ void Quit() {
+ g_main_loop_quit(loop_);
+ }
+
+ private:
+ GMainLoop* loop_;
+ bs::Benchmark stub_;
+};
+
+} // namespace
+
+int main(int argc, char** argv) {
+ MainLoop loop;
+ loop.Run();
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dbus-proxy.hh"
+#include "log-private.hh"
+
+namespace rpc_port {
+namespace benchmark {
+
+namespace {
+
+constexpr const char BUS_NAME[] = "tizen.appfw.rpcport.benchmark.dbus";
+constexpr const char OBJECT_PATH[] = "/tizen/appfw/rpcport/benchmark/dbus";
+constexpr const char INTERFACE_NAME[] = "tizen.appfw.rpcport.benchmark.dbus";
+
+}
+
+DbusProxy::DbusProxy() {
+}
+
+void DbusProxy::Connect() {
+ if (system_conn_ != nullptr)
+ return;
+
+ GError* error = nullptr;
+ system_conn_ = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
+ if (system_conn_ == nullptr) {
+ _E("g_bus_get_sync() is failed. error(%s)",
+ error ? error->message : "Unknown");
+ g_clear_error(&error);
+ }
+}
+
+int DbusProxy::Test(std::string data) const {
+ auto* msg = g_dbus_message_new_method_call(BUS_NAME,
+ OBJECT_PATH, INTERFACE_NAME, "Test");
+ if (msg == nullptr) {
+ _E("g_dbus_message_new_method_call() is failed");
+ return -1;
+ }
+ std::unique_ptr<GDBusMessage, decltype(g_object_unref)*> msg_auto(
+ msg, g_object_unref);
+
+ g_dbus_message_set_body(msg, g_variant_new("(s)", data.c_str()));
+ GError* error = nullptr;
+ auto* reply = g_dbus_connection_send_message_with_reply_sync(system_conn_, msg,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, nullptr, nullptr, &error);
+ if (reply == nullptr || error != nullptr) {
+ _E("g_dbus_connection_send_message_with_reply_sync() is failed. error(%s)",
+ error ? error->message : "Unknown");
+ g_clear_error(&error);
+ return -1;
+ }
+ std::unique_ptr<GDBusMessage, decltype(g_object_unref)*> reply_auto(
+ reply, g_object_unref);
+
+ auto* body = g_dbus_message_get_body(reply);
+ if (body == nullptr) {
+ _E("g_dbus_message_get_body() is failed");
+ return -1;
+ }
+
+ int ret = -1;
+ g_variant_get(body, "(i)", &ret);
+ return ret;
+}
+
+} // namespace benchmark
+} // namespace rpc_port
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DBUS_PROXY_HH_
+#define DBUS_PROXY_HH_
+
+#include <string>
+#include <memory>
+
+#include <gio/gio.h>
+#include <glib.h>
+
+namespace rpc_port {
+namespace benchmark {
+
+class DbusProxy {
+ public:
+ DbusProxy();
+
+ void Connect();
+ int Test(std::string data) const;
+
+ private:
+ GDBusConnection* system_conn_ = nullptr;
+};
+
+} // namespace benchmark
+} // namespace rpc_port
+
+#endif // DBUS_PROXY_HH_
#include "log-private.hh"
#include "options.hh"
#include "BenchmarkProxy.h"
+#include "dbus-proxy.hh"
namespace {
#define SERVER_PROC_NAME "org.tizen.appfw.rpc_port.benchmark"
#define SERVER_BIN "/usr/bin/rpc-port-benchmark-server"
+#define SERVER_BIN_DBUS "/usr/bin/rpc-port-benchmark-server-dbus"
namespace bp = rpc_port::BenchmarkProxy::proxy;
return;
}
- ExecuteServer();
- proxy_.reset(new bp::Benchmark(&listener_, SERVER_PROC_NAME));
-
- try {
- proxy_->Connect(true);
- } catch (const bp::Exception& e) {
- std::cerr << "Connect() failed" << std::endl;
- return;
- } catch (const std::exception& e) {
- std::cerr << "Connect() failed. " << e.what() << std::endl;
- return;
+ ExecuteServer(options_->IsDbus());
+ if (options_->IsDbus()) {
+ dbus_proxy_.Connect();
+ } else {
+ proxy_.reset(new bp::Benchmark(&listener_, SERVER_PROC_NAME));
+
+ try {
+ proxy_->Connect(true);
+ } catch (const bp::Exception& e) {
+ std::cerr << "Connect() failed" << std::endl;
+ return;
+ } catch (const std::exception& e) {
+ std::cerr << "Connect() failed. " << e.what() << std::endl;
+ return;
+ }
}
printf("%15s\t%15s\t%15s\t\t%15s\t\t%15s\n", "Iterations", "Data size",
private:
void DoTest(int iters, int size) {
bool is_func = options_->IsFunction();
+ bool is_dbus = options_->IsDbus();
StartTime();
for (int i = 0; i < iters; i++) {
continue;
}
+ if (is_dbus) {
+ int ret = dbus_proxy_.Test(std::string(size, 'a'));
+ if (ret != 0) {
+ _E("Invalid return");
+ break;
+ }
+
+ continue;
+ }
+
int ret = proxy_->Test(std::string(size, 'a'));
if (ret != 0) {
_E("Invalid return");
sec.count(), t, l);
}
- void ExecuteServer() {
+ void ExecuteServer(bool is_dbus) {
server_pid_ = fork();
if (server_pid_ == 0) {
setsid();
-
- char bin[] = { SERVER_BIN };
- char* argv[] = { bin, nullptr, nullptr };
- int ret = execv(argv[0], argv);
+ int ret;
+ if (is_dbus) {
+ char bin[] = { SERVER_BIN_DBUS };
+ char* argv[] = { bin, nullptr, nullptr };
+ ret = execv(argv[0], argv);
+ } else {
+ char bin[] = { SERVER_BIN };
+ char* argv[] = { bin, nullptr, nullptr };
+ ret = execv(argv[0], argv);
+ }
if (ret < 0) {
std::cerr << "execv() is failed. errno: " << errno << std::endl;
exit(-1);
ConnectionListener listener_;
std::chrono::system_clock::time_point start_;
pid_t server_pid_ = -1;
+ rpc_port::benchmark::DbusProxy dbus_proxy_;
};
} // namespace
Additional Options:
-f, --funcation Use function call instead of RPC
+ -d, --dbus Use Dbus method instead of TIDL RPC
-a, --all Test pre-defined test-cases
-i, --interations=<Iterations> Iterations
-s, --size=<Data size> Data size (byte)
{"iterations", required_argument, nullptr, 'i'},
{"size", required_argument, nullptr, 's'},
{"function", no_argument, nullptr, 'f'},
+ {"dbus", no_argument, nullptr, 'd'},
{"all", no_argument, nullptr, 'a'},
{0, 0, 0, 0}
};
while (true) {
- int c = getopt_long(argc, argv, "vhfai:s:", long_options,
+ int c = getopt_long(argc, argv, "vhfdai:s:", long_options,
&option_index);
if (c == -1)
break;
options->is_function_ = true;
break;
+ case 'd':
+ opt[OPT_DBUS] = true;
+ options->is_dbus_ = true;
+ break;
+
case 'a':
opt[OPT_ALL] = true;
options->is_all_ = true;
return is_all_;
}
+ bool IsDbus() const {
+ return is_dbus_;
+ }
+
private:
enum Cmd {
CMD_VERSION,
OPT_SIZE,
OPT_ALL,
OPT_FUNCTION,
+ OPT_DBUS,
OPT_MAX
};
std::string help_;
bool is_function_ = false;
bool is_all_ = false;
+ bool is_dbus_ = false;
};
} // namespace benchmark
%files
%manifest %{name}.manifest
+%config %{_sysconfdir}/dbus-1/system.d/rpc-port-benchmark.conf
%attr(0644,root,root) %{_libdir}/lib%{name}.so.*
%license LICENSE.APLv2
%{_bindir}/rpc-port-util
%{_bindir}/rpc-port-benchmark-server
+%{_bindir}/rpc-port-benchmark-server-dbus
%{_bindir}/rpc-port-benchmark-tool
%config %{_sysconfdir}/dbus-1/system.d/rpc-port.conf
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <chrono>
+#include <iostream>
+#include <rpc-port-parcel.h>
+
+#include "log-private.hh"
+
+namespace {
+
+constexpr const char SOCKET_PATH[] = "/run/.socket_test";
+
+class ClientSocket {
+ public:
+ ClientSocket() {
+ fd_ = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ }
+
+ ~ClientSocket() {
+ if (!IsClosed())
+ Close();
+ }
+
+ void Close() {
+ if (fd_ > -1) {
+ close(fd_);
+ fd_ = -1;
+ }
+ }
+
+ int Connect(const std::string& endpoint) {
+ struct sockaddr_un sockaddr = { 0, };
+ sockaddr.sun_family = AF_UNIX;
+ snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s",
+ endpoint.c_str());
+ struct sockaddr* sockaddr_ptr = reinterpret_cast<struct sockaddr*>(&sockaddr);
+ socklen_t len = sizeof(sockaddr);
+ int ret = connect(fd_, sockaddr_ptr, len);
+ if (ret < 0) {
+ ret = -errno;
+ _E("connect() is failed. errno(%d)", errno);
+ return ret;
+ }
+
+ return 0;
+ }
+
+ int Send(const void* buf, unsigned int size) {
+ const unsigned char* buffer = static_cast<const unsigned char*>(buf);
+ size_t len = size;
+ while (len) {
+ ssize_t bytes = send(fd_, buffer, len, MSG_NOSIGNAL);
+ if (bytes < 0) {
+ int ret = -errno;
+ _E("send() is failed. fd(%d), errno(%d)", fd_, errno);
+ return ret;
+ }
+
+ len -= bytes;
+ buffer += bytes;
+ }
+
+ return 0;
+ }
+
+ int Receive(void* buf, unsigned int size) {
+ unsigned char* buffer = static_cast<unsigned char*>(buf);
+ size_t len = size;
+ while (len) {
+ ssize_t bytes = read(fd_, buffer, len);
+ if (bytes == 0) {
+ _W("EOF. fd(%d)", fd_);
+ return -EIO;
+ }
+
+ if (bytes < 0)
+ return -errno;
+
+ len -= bytes;
+ buffer += bytes;
+ }
+
+ return 0;
+ }
+
+ bool IsClosed() {
+ return fd_ < 0 ? true : false;
+ }
+
+ private:
+ int fd_ = -1;
+};
+
+std::chrono::system_clock::time_point start_;
+
+void StartTime() {
+ start_ = std::chrono::system_clock::now();
+}
+
+void EndTime(int iters, int size) {
+ std::chrono::duration<double> sec = std::chrono::system_clock::now() - start_;
+ double t = size * iters * 8 / sec.count() / 1024 / 1024;
+ double l = sec.count() * 1000 / iters;
+
+ printf("%10d\t%10dByte\t%15.4fs\t%15.4fMb/s\t%15.4fms\n", iters, size,
+ sec.count(), t, l);
+}
+
+void DoTest(ClientSocket& sk, int iters, int size) {
+ StartTime();
+ rpc_port_parcel_h p;
+ rpc_port_parcel_create(&p);
+ for (int i = 0; i < iters; i++) {
+
+
+ std::string data(size, 'a');
+ rpc_port_parcel_write_string(p, data.c_str());
+
+ int ret = -1;
+ sk.Send(&size, sizeof(size));
+ sk.Send(data.c_str(), size);
+ sk.Receive(&ret, sizeof(ret));
+ if (ret != 9216) {
+ _E("Invalid return");
+ exit(1);
+ }
+ }
+ rpc_port_parcel_destroy(p);
+ EndTime(iters, size);
+}
+
+}
+
+int main(int argc, char** argv) {
+ ClientSocket sk;
+ sk.Connect(SOCKET_PATH);
+
+ printf("%15s\t%15s\t%15s\t\t%15s\t\t%15s\n", "Iterations", "Data size",
+ "Time", "Throughput", "Latency");
+ DoTest(sk, 4000, 10);
+ DoTest(sk, 4000, 20);
+ DoTest(sk, 4000, 100);
+ DoTest(sk, 4000, 200);
+ DoTest(sk, 2000, 1000);
+ DoTest(sk, 2000, 2000);
+ DoTest(sk, 1000, 10000);
+ DoTest(sk, 1000, 20000);
+ DoTest(sk, 1000, 30000);
+ DoTest(sk, 1000, 40000);
+ DoTest(sk, 1000, 50000);
+ DoTest(sk, 1000, 60000);
+ DoTest(sk, 500, 100000);
+
+ return 0;
+}