--- /dev/null
+#include <diagnostics.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "log.h"
+#include "process.h"
+#include "data_source.h"
+#include "utils.h"
+
+struct dump_options {
+ int fd;
+ int pid;
+ long last;
+ char *type;
+ unsigned long long request_time;
+};
+
+static void dump_help(struct dump_options *opt)
+{
+ dprintf(opt->fd,
+ "Options:\n"
+ " -p, --pid <number> Dump only process with given pid\n"
+ " -t, --type <module> Dump only specified module, ex. cpu, mem, io or fd\n"
+ " -l, --last <sec> Dump data from last <sec> seconds\n"
+ " -h, --help Dump this help message\n");
+}
+
+static void dump_process_data(struct proc_info *process, struct dump_options *opt)
+{
+ struct data_source *ds;
+ struct smpl_container *sample_container;
+ struct sample_s *sample;
+ int foreground = process_is_foreground(process);
+ double sample_offset;
+
+ dprintf(opt->fd, "%s (%d)\n", process->name, process->pid);
+
+ /* Iterate over data sources */
+ for (int j = 0; j < data_sources_get_n(); j++) {
+ ds = &(process->data_sources[j]);
+
+ /* Skip if type doesn't match */
+ if (opt->type && strncmp(opt->type, ds->param_name, strlen(opt->type)) != 0)
+ continue;
+
+ dprintf(opt->fd, "\t%s\n", ds->param_name);
+
+ /* Iterate over samples */
+ sample_container = foreground ? &(ds->data_fg) : &(ds->data_bg);
+ list_for_each_entry(sample, &sample_container->samples, node) {
+ sample_offset = (opt->request_time - sample->measure_time) * 1.0 / USEC_PER_SEC;
+ if (sample_offset < opt->last)
+ dprintf(opt->fd, "\t\t%s (+%.3fs)\n", smpl2str(sample), sample_offset);
+ }
+ }
+}
+
+static int parse_params(char **params, int params_size, struct dump_options *opt)
+{
+ static struct option long_options[] = {
+ {"pid", required_argument, NULL, 'p'},
+ {"type", required_argument, NULL, 't'},
+ {"last", required_argument, NULL, 'l'},
+ {"help", no_argument, NULL, 'h'},
+ {}
+ };
+ int c;
+ char **params_ex;
+
+ /* Insert additional parameter at the begining of the array for getopt to work */
+ params_ex = alloca((params_size + 1) * sizeof(char*));
+ memcpy(¶ms_ex[1], params, params_size * sizeof(char*));
+ params_ex[0] = 0;
+
+ optind = 0;
+ while ((c = getopt_long_only(params_size + 1, params_ex, "p:t:l:h", long_options, NULL)) >= 0) {
+ switch (c) {
+ case 'p':
+ opt->pid = atoi(optarg);
+ break;
+
+ case 't':
+ if (opt->type)
+ free(opt->type);
+
+ opt->type = strdup(optarg);
+ if (!opt->type) {
+ _E("Unable to allocate memory");
+ return -ENOMEM;
+ }
+ break;
+
+ case 'l':
+ opt->last = strtol(optarg, NULL, 10);
+ break;
+
+ case 'h':
+ dump_help(opt);
+ return -ECANCELED;
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void data_request_cb(diagnostics_data_h data, char **params, int params_size, diagnostics_ctx_h ctx, void *user_data)
+{
+ struct proc_info *process, *next;
+ struct list_head *process_table = process_table_get();
+ struct dump_options opt;
+ int ret;
+
+ opt.fd = -1;
+ opt.pid = 0;
+ opt.type = NULL;
+ opt.request_time = time_now();
+ opt.last = opt.request_time / USEC_PER_SEC;
+
+ ret = diagnostics_data_get_fd(data, &opt.fd);
+ if (ret) {
+ _E("Unable to get file descriptor to write data: %d", ret);
+ goto cleanup;
+ }
+
+ ret = parse_params(params, params_size, &opt);
+ if (ret) {
+ if (ret != -ECANCELED)
+ _E("Unable to parse data request parameters: %d", ret);
+ goto cleanup;
+ }
+
+ if (opt.pid) {
+ /* Dump one process */
+ process = process_get_by_pid(opt.pid);
+ if (!process) {
+ _E("No such process: %d", opt.pid);
+ goto cleanup;
+ }
+
+ dump_process_data(process, &opt);
+ } else {
+ /* Dump all processes */
+ for (int i = 0; i < HASH_TABLE_SIZE; i++)
+ list_for_each_entry_safe(process, next, &process_table[i], node)
+ dump_process_data(process, &opt);
+ }
+
+cleanup:
+ if (opt.type)
+ free(opt.type);
+ diagnostics_data_destroy(data);
+}
+
+int diagnostic_dump_init(void)
+{
+ int ret;
+
+ ret = diagnostics_set_client_id("org.tizen.stability-monitor");
+ if (ret) {
+ _E("Unable to set diagnostic client id: %d", ret);
+ return ret;
+ }
+
+ ret = diagnostics_set_data_request_cb(data_request_cb, NULL);
+ if (ret) {
+ _E("Unable to set data request cb: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of stability-monitor
+ *
+ * Copyright © 2021 Samsung Electronics
+ *
+ * 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 DIAGNOSTIC_DUMP_H
+#define DIAGNOSTIC_DUMP_H
+
+int diagnostic_dump_init(void);
+
+#endif // DIAGNOSTIC_DUMP_H