cpp/elf/Elf.cpp \
\
cpp/auxd/auxd_client.cpp \
- cpp/auxd/auxd_client_c.cpp
+ cpp/auxd/auxd_client_c.cpp \
+\
+ cpp/memd/memd_client.cpp \
+ cpp/memd/memd_client_c.cpp
TARGET = swap_manager
# AUXC
AUX_PROTOBUF_DIR = ../src/auxd/protocol
-protobuf_generated:
+protobuf_generated_auxd:
protoc --cpp_out=$(GENERATED_DIR) --proto_path=$(AUX_PROTOBUF_DIR) $(AUX_PROTOBUF_DIR)/auxd_metadata.proto
SRC_CPP += $(GENERATED_DIR)/auxd_metadata.pb.cc
+
+# MEMD
+MEMD_PROTOBUF_DIR = ../src/memd/protocol
+protobuf_generated_memd:
+ protoc --cpp_out=$(GENERATED_DIR) --proto_path=$(MEMD_PROTOBUF_DIR) $(MEMD_PROTOBUF_DIR)/memd_metadata.proto
+
+SRC_CPP += $(GENERATED_DIR)/memd_metadata.pb.cc
+
+
+protobuf_generated: protobuf_generated_auxd protobuf_generated_memd
LDFLAGS += -lprotobuf-lite -lswaputils -L../build/lib
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include "memd_client.h"
+#include <memory>
+#include <stdexcept>
+#include <utils/unix/unix_client.h>
+#include <utils/socket.h>
+
+#include <memd/protocol/memd.h>
+#include <memd_metadata.pb.h>
+
+
+template <class In, class Out>
+void do_request(IPC::Client &client, unsigned int id, const In &in_type, Out &out_type)
+{
+ std::string in;
+
+ if (!in_type.SerializeToString(&in))
+ throw std::runtime_error("Cannot serialize");
+
+ std::string out;
+ client.request(id, in, out);
+ if (!out_type.ParseFromString(out))
+ throw std::runtime_error("Cannot deserialize");
+}
+
+static int do_read_file(IPC::Client &client, const std::string &path,
+ std::string &out, std::string &err)
+{
+ MEMD::ReadFileRequest request;
+ request.set_path(path);
+
+ MEMD::ReadFileAnswer answer;
+ do_request(client, MEMD_READ_FILE, request, answer);
+
+ out = answer.data();
+ err = answer.error();
+ return answer.success();
+}
+
+
+MemdClient::MemdClient(const std::string &socket_path) :
+ socket_path_(socket_path)
+{
+ std::unique_ptr<Unix::Client> unix_client(new Unix::Client());
+ Socket *socket = unix_client->connect(socket_path);
+ std::unique_ptr<IPC::Client> ipc_client(new IPC::Client(socket));
+
+ unix_client_ = std::move(unix_client);
+ ipc_client_ = std::move(ipc_client);
+}
+
+bool MemdClient::read_file(const std::string &path, std::string &out)
+{
+ std::string err;
+ int ret = do_read_file(*ipc_client_.get(), path, out, err);
+ if (!ret)
+ throw std::runtime_error(err);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef MEMD_CLIENT_H
+#define MEMD_CLIENT_H
+
+
+#include <string>
+#include <memory>
+#include <utils/socket.h>
+#include <utils/unix/unix_client.h>
+#include <utils/ipc/ipc_client.h>
+
+
+class MemdClient
+{
+public:
+ MemdClient(const std::string &socket_path);
+
+ bool read_file(const std::string &path, std::string &out);
+
+private:
+ std::string socket_path_;
+
+ std::unique_ptr<IPC::Client> ipc_client_;
+ std::unique_ptr<Unix::Client> unix_client_;
+};
+
+
+#endif // MEMD_CLIENT_H
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include "memd_client_c.h"
+#include "memd_client.h"
+#include <swap_debug.h>
+#include <string>
+
+
+struct memd_client {
+ MemdClient *client;
+ std::string err;
+};
+
+
+struct memd_buffer {
+ std::string data;
+};
+
+
+struct memd_client *memd_client_create(void)
+{
+ struct memd_client *c = nullptr;
+
+ try {
+ c = new memd_client();
+ c->client = nullptr;
+ } catch (...) {
+ LOGE("Unknown error\n");
+ }
+
+ return c;
+}
+
+void memd_client_destroy(struct memd_client *c)
+{
+ delete c->client;
+ delete c;
+}
+
+int memd_client_init(struct memd_client *c, const char *socket_path)
+{
+ c->err.clear();
+
+ if (c->client) {
+ c->err = "Already init";
+ return -EBUSY;
+ }
+
+ try {
+ c->client = new MemdClient(socket_path);
+ return 0;
+ } catch (const std::runtime_error &err) {
+ c->err = err.what();
+ } catch (...) {
+ c->err = "Unknown error";
+ }
+
+ return -EINVAL;
+}
+
+void memd_client_uninit(struct memd_client *c)
+{
+ delete c->client;
+ c->client = nullptr;
+}
+
+bool memd_client_read_file(struct memd_client *c, const char *path,
+ struct memd_buffer *b /* out */)
+{
+ c->err.clear();
+
+ try {
+ return c->client->read_file(path, b->data);
+ } catch (const std::runtime_error &err) {
+ c->err = err.what();
+ } catch (...) {
+ c->err = "Unknown error";
+ }
+
+ return false;
+}
+
+
+
+struct memd_buffer *memd_buffer_create(void)
+{
+ struct memd_buffer *b = nullptr;
+
+ try {
+ b = new memd_buffer();
+ } catch (...) {
+ LOGE("Unknown error\n");
+ }
+
+ return b;
+}
+
+void memd_buffer_destroy(struct memd_buffer *b)
+{
+ delete b;
+}
+
+size_t memd_buffer_size(struct memd_buffer *b)
+{
+ return b->data.size();
+}
+
+const char *memd_buffer_data(struct memd_buffer *b)
+{
+ return b->data.data();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef MEMD_CLIENT_C_H
+#define MEMD_CLIENT_C_H
+
+
+#include <stddef.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct memd_client;
+struct memd_buffer;
+
+struct memd_client *memd_client_create(void);
+void memd_client_destroy(struct memd_client *c);
+
+int memd_client_init(struct memd_client *c, const char *socket_path);
+void memd_client_uninit(struct memd_client *c);
+
+bool memd_client_read_file(struct memd_client *c, const char *path,
+ struct memd_buffer *b /* out */);
+
+
+struct memd_buffer *memd_buffer_create(void);
+void memd_buffer_destroy(struct memd_buffer *b);
+
+size_t memd_buffer_size(struct memd_buffer *b);
+const char *memd_buffer_data(struct memd_buffer *b);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // MEMD_CLIENT_C_H
struct auxd_client;
+struct memd_client;
typedef struct
{
char appPath[128]; // application executable path
struct auxd_client *auxd_client;
+ struct memd_client *memd_client;
} __da_manager;
extern __da_manager manager;
static const int ES_TIMEOUT = 30;
static const char CMD_AUXD_PATH[] = "/tmp/swap/auxd";
+static const char CMD_MEMD_PATH[] = "/tmp/swap/memd";
static const char CMD_MODULE_PATH[] = "/tmp/swap/module";
return run_service(CMD_AUXD_PATH, "", ES_TIMEOUT);
}
+int es_memd_run(void)
+{
+ return run_service(CMD_MEMD_PATH, "", ES_TIMEOUT);
+}
+
int es_modules_load(void)
{
return run_service(CMD_MODULE_PATH, "load", ES_TIMEOUT);
/* auxd */
int es_auxd_run(void);
+/* memd */
+int es_memd_run(void);
+
/* modules */
int es_modules_load(void);
int es_modules_unload(void);
#include "smack.h"
#include "extern_service.h"
#include "cpp/auxd/auxd_client_c.h"
+#include "cpp/memd/memd_client_c.h"
#include "cpp/features/feature_manager_c.h"
#define SINGLETON_LOCKFILE "/tmp/da_manager.lock"
}
+static int manager_memd_client_init(__da_manager *m)
+{
+ const char MEMD_SOCKET_PATH[] = "/tmp/swap_memd.socket";
+
+ int ret;
+ struct memd_client *c;
+
+ c = memd_client_create();
+ if (!c)
+ return -ENOMEM;
+
+ ret = memd_client_init(c, MEMD_SOCKET_PATH);
+ if (ret) {
+ memd_client_destroy(c);
+ return ret;
+ }
+
+ m->memd_client = c;
+ LOGI("Connect to socket '%s'\n", MEMD_SOCKET_PATH);
+
+ return ret;
+}
+
+static void manager_memd_client_uninit(__da_manager *m)
+{
+ memd_client_uninit(m->memd_client);
+ memd_client_destroy(m->memd_client);
+
+ m->memd_client = NULL;
+}
+
// =============================================================================
// util functions
// =============================================================================
return -1;
}
+ ret = es_memd_run();
+ if (ret) {
+ LOGE("Cannot run memd, ret=%d\n", ret);
+ return -1;
+ }
+
ret = manager_auxd_client_init(&manager);
if (ret) {
LOGE("Cannot init aux client, ret=%d\n", ret);
return -1;
}
+ ret = manager_memd_client_init(&manager);
+ if (ret) {
+ LOGE("Cannot init memd client, ret=%d\n", ret);
+ return -1;
+ }
+
if (ks_init()) {
LOGE("Cannot init kernel space");
return -1;
close(manager.host.data_socket);
}
+ manager_memd_client_uninit(&manager);
manager_auxd_client_uninit(&manager);
LOGI("return\n");
#include "device_vconf.h"
#include "device_camera.h"
#include "swap_debug.h"
+#include <cpp/memd/memd_client_c.h>
// defines for runtime environment
#define FOR_EACH_CPU
#define BUF_INC_SIZE (512 * 1024) /* maximal SMAPS I saw 2 MB */
/* reads file contents into memory */
-static char* cread(const char* path)
+static char *cread(const char *path, size_t *size)
{
- /* once allocated area for reads */
- static char* text = NULL;
- static size_t size = 0;
+ char *buf = NULL;
- ssize_t ret;
- char* ptr = text;
- size_t cap = size;
- int fd = open(path, O_RDONLY);
-
- if (fd < 0) {
+ struct memd_buffer *b = memd_buffer_create();
+ if (!b)
return NULL;
- }
- do {
- /* ensure we have enough space */
- if (cap == 0) {
- ptr = (char*)realloc(text, size + BUF_INC_SIZE);
- if (ptr == NULL) {
- ret = -1;
- break;
- }
+ if (!memd_client_read_file(manager.memd_client, path, b))
+ goto free_all;
- text = ptr;
- ptr = text + size;
- cap = BUF_INC_SIZE;
- size += BUF_INC_SIZE;
- }
- ret = read(fd, ptr, cap);
- if (ret == 0) {
- *ptr = 0;
- } else if (ret > 0) {
- cap -= ret;
- ptr += ret;
- }
- } while (ret > 0);
- close(fd);
+ size_t sz = memd_buffer_size(b);
+ if (!sz)
+ goto free_all;
+
+ buf = malloc(sz + 1);
+ if (!buf)
+ goto free_all;
- return (ret < 0 ? NULL : text);
-} /* cread */
+ memcpy(buf, memd_buffer_data(b), sz);
+ buf[sz] = '\0';
+ if (size)
+ *size = sz;
+
+free_all:
+ memd_buffer_destroy(b);
+
+ return buf;
+}
/* like fgets/gets but adjusting contents pointer */
static inline char* cgets(char** contents)
int major, minor;
char flags[4];
- buf_start = cread(cmd);
+ buf_start = cread(cmd, NULL);
if (buf_start == NULL)
goto error;
}
+static bool save_to_tmpfile(char *path, int suffixlen,
+ const char *data, size_t len)
+{
+ int fd = mkstemps(path, suffixlen);
+ if (fd == -1) {
+ LOGE("Cannot make temp file, errno=%d\n", errno);
+ return false;
+ }
+
+ /* TODO: check return value */
+ write(fd, data, len);
+ close(fd);
+
+ return true;
+}
+
+static bool save_request_to_tmpfile(const char *in_path,
+ char *out_path, int out_suffixlen)
+{
+ size_t size;
+ char *buf = cread(in_path, &size);
+ if (!buf) {
+ LOGE("Cannot 'cread' '%s' file\n", in_path);
+ return false;
+ }
+
+ bool ret = save_to_tmpfile(out_path, out_suffixlen, buf, size);
+ free(buf);
+
+ return ret;
+}
+
// return 0 for normal case
// return negative value for error case
static int parse_proc_smaps_file_bypid(char *path, proc_t *P)
{
#define MIN_SMAP_BLOCKLINE 50
- char filename[PROCPATH_MAX];
+ char path_smaps[PROCPATH_MAX];
proc_t proc_tmp;
FILE* fp;
P->gem_pss = 0;
// read from smaps file
- snprintf(filename, sizeof(filename), "%s/smaps", path);
- fp = fopen(filename, "r");
+ snprintf(path_smaps, sizeof(path_smaps), "%s/smaps", path);
+
+ /* FIXME: rework this code (save to file, read file, remove file) */
+ const int tmp_suffixlen = 6;
+ char tmp_path[] = "/tmp/swap_smaps_XXXXXX.smaps";
+ bool ret = save_request_to_tmpfile(path_smaps, tmp_path, tmp_suffixlen);
+ if (!ret) {
+ LOGE("Cannot save smaps to tmpfile\n");
+ return -1;
+ }
+ fp = fopen(tmp_path, "r");
if(fp == NULL){
+ LOGE("Open '%s'\n", tmp_path);
+ remove(tmp_path);
return -1;
}
P->sh_mem_dirty *= 1024;
fclose(fp);
+ remove(tmp_path);
return 0;
}
<!-- swap_auxd -->
<filesystem path="/usr/bin/swap_auxd" label="System" exec_label="User"/>
+ <!-- swap_memd -->
+ <filesystem path="/usr/bin/swap_memd" label="System" exec_label="User"/>
+
<!-- libswaputils.so -->
<filesystem path="/usr/lib/libswaputils.so" label="_"/>
install -m 0644 systemd/swap_auxd.path %{buildroot}%{_unitdir}/
ln -s ../swap_auxd.path %{buildroot}%{_unitdir}/multi-user.target.wants/
+# swap_memd
+install -m 0644 systemd/swap_memd.service %{buildroot}%{_unitdir}/
+install -m 0644 systemd/swap_memd.socket %{buildroot}%{_unitdir}/
+install -m 0644 systemd/swap_memd.path %{buildroot}%{_unitdir}/
+ln -s ../swap_memd.path %{buildroot}%{_unitdir}/multi-user.target.wants/
+
# tmpfiles.d
mkdir -p %{buildroot}%{_tmpfilesdir}
install -m 0666 systemd/swap.conf %{buildroot}%{_tmpfilesdir}/swap.conf
%{_unitdir}/swap_auxd.path
%{_unitdir}/multi-user.target.wants/swap_auxd.path
+# swap_memd
+%{_unitdir}/swap_memd.socket
+%{_unitdir}/swap_memd.service
+%{_unitdir}/swap_memd.path
+%{_unitdir}/multi-user.target.wants/swap_memd.path
+
%{_tmpfilesdir}/swap.conf
%{_udevrulesdir}/99-swap_dev.rules
# auxd
%{_bindir}/swap_auxd
+# swap_memd
+%{_bindir}/swap_memd
+
%changelog
add_subdirectory(utils)
add_subdirectory(auxd)
+add_subdirectory(memd)
--- /dev/null
+cmake_minimum_required(VERSION 2.8)
+
+project(memd)
+set(PROJECT_NAME swap_memd)
+
+find_package(Protobuf REQUIRED)
+
+
+# setup protobuf
+set(PROTO_DIR ${CMAKE_CURRENT_SOURCE_DIR}/protocol)
+
+protobuf_generate_cpp(
+ PROTO_SRCS
+ PROTO_HDRS
+ ${PROTO_DIR}/memd_metadata.proto
+)
+
+
+# headers setup
+include_directories(
+ ${PROTO_DIR} # protocol headers
+ ${CMAKE_CURRENT_BINARY_DIR} # generated protobuf headers
+ ${CMAKE_CURRENT_SOURCE_DIR}/../utils/ # utils headers
+)
+
+
+# setup sorces
+set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
+set(SRC
+ ${PROTO_SRCS}
+ ${SRC_DIR}/main.cpp
+)
+
+
+# setup linker
+link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
+
+add_executable(${PROJECT_NAME} ${SRC})
+target_link_libraries(
+ ${PROJECT_NAME}
+ ${PROTOBUF_LITE_LIBRARIES}
+ libswaputils.so
+ libsystemd.so
+)
+
+
+# install
+install(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#ifndef MEMD_H
+#define MEMD_H
+
+
+enum MemdIPC {
+ MEMD_READ_FILE,
+ MEMD_EXIT,
+ MEMD_CNT
+};
+
+
+#endif // MEMD_H
--- /dev/null
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+
+package MEMD;
+
+message ReadFileRequest {
+ required string path = 1;
+}
+
+message ReadFileAnswer {
+ required bool success = 1;
+ required string error = 2;
+ required bytes data = 3;
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <systemd/sd-daemon.h>
+#include <event_loop.h>
+#include <memd.h>
+#include <memd_metadata.pb.h>
+
+
+static const int CONNECT_TIMEOUT = 10 * 1000;
+static const char SOCKET_PATH[] = "/tmp/swap_memd.socket";
+
+
+static bool read_file(const char *filename, std::string &out)
+{
+ std::ifstream in(filename, std::ios::in | std::ios::binary);
+ if (in) {
+ out = std::string(std::istreambuf_iterator<char>(in),
+ std::istreambuf_iterator<char>());
+ return true;
+ }
+
+ return false;
+}
+
+static void do_memd_read_file(const MEMD::ReadFileRequest &request,
+ MEMD::ReadFileAnswer &answer)
+{
+ bool ret = false;
+ std::string out;
+ std::string err;
+
+ try {
+ ret = read_file(request.path().c_str(), out);
+ } catch (...) {
+ err = "Cannot read file: " + request.path();
+ }
+
+ answer.set_success(ret);
+ answer.set_error(err);
+ answer.set_data(out);
+}
+
+static void try_memd_read_file(void *user_data, const std::string &in, std::string &out)
+{
+ MEMD::ReadFileRequest request;
+ MEMD::ReadFileAnswer answer;
+
+ if (!request.ParseFromString(in))
+ throw std::runtime_error("Cannot parse: in -> ReadFileRequest");
+
+ do_memd_read_file(request, answer);
+
+ if (!answer.SerializeToString(&out))
+ throw std::runtime_error("Cannot serialize: ReadFileAnswer -> out");
+}
+
+static EventLoop::HandlerCode memd_read_file(void *user_data,
+ const std::string &in, std::string &out)
+{
+ try {
+ try_memd_read_file(user_data, in, out);
+ return EventLoop::HC_SUCCESS;
+ } catch (const google::protobuf::FatalException &e) {
+ throw std::runtime_error(e.what());
+ } catch (...) {
+ throw std::runtime_error(std::string("Unknown exeption in: ") + __func__);
+ }
+
+ return EventLoop::HC_ERROR;
+}
+
+static EventLoop::HandlerCode memd_exit(void *user_data,
+ const std::string &in, std::string &out)
+{
+ return EventLoop::HC_STOP;
+}
+
+static EventLoop::Handler recv_handler[MEMD_CNT] = {
+ [MEMD_READ_FILE] = memd_read_file,
+ [MEMD_EXIT] = memd_exit,
+};
+
+
+
+static EventLoop *g_loop;
+
+static void signal_handler(int sig)
+{
+ if (sig == SIGTERM) {
+ // shut down
+ g_loop->stop();
+
+ // reaset signal
+ signal(SIGTERM, SIG_DFL);
+ } else if (sig == SIGHUP) {
+ // reload config
+ }
+}
+
+static void signal_setup()
+{
+ signal(SIGTERM, signal_handler);
+ signal(SIGHUP, signal_handler);
+}
+
+static void do_main()
+{
+ signal_setup();
+
+ EventLoop::RecvData recv_data(nullptr, recv_handler, MEMD_CNT);
+
+ EventLoop event_loop;
+ g_loop = &event_loop;
+ g_loop->init(SOCKET_PATH);
+
+ sd_notify(0, "READY=1");
+ g_loop->run(recv_data, CONNECT_TIMEOUT);
+ sd_notify(0, "STOPPING=1");
+
+ g_loop->uninit();
+}
+
+
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+
+ try {
+ do_main();
+ } catch (const std::runtime_error &err) {
+ std::cerr << err.what() << std::endl;
+ ret = -1;
+ } catch (...) {
+ std::cerr << "main: Unknown exception" << std::endl;
+ ret = -1;
+ }
+
+ return ret;
+}
--- /dev/null
+[Unit]
+Description=swap_memd trigger
+
+[Path]
+PathExists=/tmp/swap/memd
+
+[Install]
+WantedBy=multi-user.target
--- /dev/null
+[Unit]
+Description=swap_memd service
+
+[Service]
+Type=notify
+NotifyAccess=main
+
+User=owner
+Group=users
+SmackProcessLabel=System
+Sockets=swap_memd.socket
+
+PermissionsStartOnly=true
+ExecStart=/usr/bin/swap_memd
+ExecStartPost=/bin/rm -f /tmp/swap/memd
+
+StandardOutput=journal+console
+StandardError=journal+console
--- /dev/null
+[Unit]
+Description=swap_memd socket
+
+[Socket]
+ListenStream=/tmp/swap_memd.socket
+SmackLabelIPIn=*
+SmackLabelIPOut=@
+
+[Install]
+WantedBy=sockets.target