, m_dbus_systemd_manager_interface("org.freedesktop.systemd1.Manager")
, m_dbus_systemd_properties_interface("org.freedesktop.DBus.Properties")
, m_dbus_systemd_service_interface("org.freedesktop.systemd1.Service")
+ , m_reloadingToken("Reloading")
{
dbus_error_init(&m_err);
connectToDBus();
finalizeMsgReply();
}
+void DBusAccess::reloadDbusManager() {
+ newMethodCall("Reload");
+ sendMsgWithReply();
+ getMsgReply();
+ finalizeMsgReply();
+ m_runningJobs.insert(m_reloadingToken);
+}
+
void DBusAccess::requestName() {
dbus_bus_request_name(m_conn, m_dbus_client_name.c_str(),
DBUS_NAME_FLAG_REPLACE_EXISTING , &m_err);
"Error in dbus_message_iter_append_basic");
}
+void DBusAccess::appendToMsg(const char *const *argument) {
+ DBusMessageIter iter;
+ DBusMessageIter subIter;
+ int ret;
+
+ dbus_message_iter_init_append(m_msg, &iter);
+ ret = dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING,
+ &subIter);
+ RUNNER_ASSERT_MSG(ret != 0,
+ "Error in dbus_message_iter_open_container");
+ for (auto str = argument; *str; str++) {
+ int ret = dbus_message_iter_append_basic(&subIter, DBUS_TYPE_STRING, str);
+ RUNNER_ASSERT_MSG(ret != 0,
+ "Error in dbus_message_iter_append_basic");
+ }
+ ret = dbus_message_iter_close_container(&iter, &subIter);
+ RUNNER_ASSERT_MSG(ret != 0,
+ "Error in dbus_message_iter_close_container");
+}
+
+void DBusAccess::appendToMsg(bool argument) {
+ DBusMessageIter iter;
+
+ dbus_message_iter_init_append(m_msg, &iter);
+ int b = argument ? 1 : 0;
+ int ret = dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN,
+ &b);
+ RUNNER_ASSERT_MSG(ret != 0,
+ "Error in dbus_message_iter_append_basic");
+}
+
void DBusAccess::sendMsgWithReply() {
int ret = dbus_connection_send_with_reply(m_conn, m_msg, &m_pending, -1);
RUNNER_ASSERT_MSG(ret == 1,
connect();
addBusMatch("JobRemoved");
addBusMatch("JobNew");
+ addBusMatch("Reloading");
dbus_connection_flush(m_conn);
dbus_connection_add_filter(m_conn,
messageHandler,
m_runningJobs.insert(handleObjectPathMsgReply());
}
+void DBusAccess::sendMaskToService() {
+ const char *mask[] = {m_service_name.c_str(), nullptr};
+ newMethodCall("MaskUnitFiles");
+ appendToMsg(mask);
+ appendToMsg(true);
+ appendToMsg(true);
+ sendMsgWithReply();
+ getMsgReply();
+ finalizeMsgReply();
+}
+
+void DBusAccess::sendUnmaskToService() {
+ const char *mask[] = {m_service_name.c_str(), nullptr};
+ newMethodCall("UnmaskUnitFiles");
+ appendToMsg(mask);
+ appendToMsg(true);
+ sendMsgWithReply();
+ getMsgReply();
+ finalizeMsgReply();
+}
+
uint32_t DBusAccess::getUIntProperty(const char *interface, const char *property)
{
m_msg = dbus_message_new_method_call(m_dbus_systemd_destination.c_str(),
self->signalJobRemovedHandler(msg);
else if (self->isSignal(msg, "JobNew"))
self->signalJobNewHandler(msg);
+ else if (self->isSignal(msg, "Reloading"))
+ self->signalReloadingHandler(msg);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
m_runningJobs.insert(path);
}
+void DBusAccess::signalReloadingHandler(DBusMessage *msg) {
+ DBusMessageIter iter;
+ RUNNER_ASSERT_MSG(dbus_message_iter_init(msg, &iter) != 0,
+ "Message has no arguments");
+
+ if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&iter)) {
+ RUNNER_FAIL_MSG("boolean type expected");
+ }
+ bool active;
+ dbus_message_iter_get_basic(&iter, &active);
+
+ if (active)
+ m_runningJobs.insert(m_reloadingToken);
+ else
+ m_runningJobs.erase(m_reloadingToken);
+}
+
void DBusAccess::waitForRunningJobsFinish() {
while (!m_runningJobs.empty())
dbus_connection_read_write_dispatch(m_conn, -1);
return static_cast<pid_t>(getUIntProperty(m_dbus_systemd_service_interface.c_str(), "MainPID"));
}
+void DBusAccess::maskService() {
+ sendMaskToService();
+ reloadDbusManager();
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
+void DBusAccess::unmaskService() {
+ sendUnmaskToService();
+ reloadDbusManager();
+ waitForRunningJobsFinish();
+ sendResetFailedToService();
+}
+
DBusAccess::~DBusAccess() {
dbus_connection_close(m_conn);
if (m_conn)
void stopService();
void restartService();
pid_t getServicePid();
+ void maskService();
+ void unmaskService();
virtual ~DBusAccess();
private:
void connect();
void addBusMatch(const char *member);
void subscribeSignals();
+ void reloadDbusManager();
void requestName();
void getUnitPath();
void newMethodCall(const char *method);
void appendToMsg(const char *argument);
+ void appendToMsg(const char *const *argument);
+ void appendToMsg(bool argument);
void sendMsgWithReply();
void getMsgReply();
std::string handleObjectPathMsgReply();
void connectToDBus();
void sendToService(const char *method);
+ void sendMaskToService();
+ void sendUnmaskToService();
uint32_t getUIntProperty(const char *interface, const char *property);
void sendResetFailedToService();
bool isSignal(DBusMessage *msg, const char *signal);
void signalJobRemovedHandler(DBusMessage *msg);
void signalJobNewHandler(DBusMessage *msg);
+ void signalReloadingHandler(DBusMessage *msg);
void waitForRunningJobsFinish();
DBusConnection *m_conn;
const std::string m_dbus_systemd_service_interface;
std::set<std::string> m_runningJobs;
+ const std::string m_reloadingToken;
};
#endif // _DBUS_ACCESS_H_