#include <common/runas.h>
#include <lttng/save-internal.h>
+#include "kernel.h"
#include "save.h"
#include "session.h"
#include "syscall.h"
return ret;
}
-/* TODO: save/restore tracker pid */
-
static
int save_kernel_context(struct config_writer *writer,
struct lttng_kernel_context *ctx)
return ret;
}
+static
+int save_pid_tracker(struct config_writer *writer,
+ struct ltt_session *sess, int domain)
+{
+ int ret = 0;
+ ssize_t nr_pids = 0, i;
+ int32_t *pids = NULL;
+
+ switch (domain) {
+ case LTTNG_DOMAIN_KERNEL:
+ {
+ nr_pids = kernel_list_tracker_pids(sess->kernel_session, &pids);
+ if (nr_pids < 0) {
+ ret = LTTNG_ERR_KERN_LIST_FAIL;
+ goto end;
+ }
+ break;
+ }
+ case LTTNG_DOMAIN_UST:
+ {
+ nr_pids = trace_ust_list_tracker_pids(sess->ust_session, &pids);
+ if (nr_pids < 0) {
+ ret = LTTNG_ERR_UST_LIST_FAIL;
+ goto end;
+ }
+ break;
+ }
+ case LTTNG_DOMAIN_JUL:
+ case LTTNG_DOMAIN_LOG4J:
+ case LTTNG_DOMAIN_PYTHON:
+ default:
+ ret = LTTNG_ERR_UNKNOWN_DOMAIN;
+ goto end;
+ }
+
+ /* Only create a pid_tracker if enabled or untrack all */
+ if (nr_pids != 1 || (nr_pids == 1 && pids[0] != -1)) {
+ ret = config_writer_open_element(writer,
+ config_element_pid_tracker);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ ret = config_writer_open_element(writer,
+ config_element_targets);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ for (i = 0; i < nr_pids; i++) {
+ ret = config_writer_open_element(writer,
+ config_element_target_pid);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ ret = config_writer_write_element_unsigned_int(writer,
+ config_element_pid, pids[i]);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ /* /pid_target */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ }
+
+ /* /targets */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ /* /pid_tracker */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ }
+end:
+ free(pids);
+ return ret;
+}
+
static
int save_domains(struct config_writer *writer, struct ltt_session *session)
{
goto end;
}
+ ret = config_writer_open_element(writer,
+ config_element_trackers);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_KERNEL);
+ if (ret) {
+ goto end;
+ }
+
+ /* /trackers */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
/* /domain */
ret = config_writer_close_element(writer);
if (ret) {
goto end;
}
+ ret = config_writer_open_element(writer,
+ config_element_trackers);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ ret = save_pid_tracker(writer, session, LTTNG_DOMAIN_UST);
+ if (ret) {
+ goto end;
+ }
+
+ /* /trackers */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
/* /domain */
ret = config_writer_close_element(writer);
if (ret) {
extern const char * const config_element_shared_memory_path;
extern const char * const config_element_pid_tracker;
extern const char * const config_element_trackers;
+extern const char * const config_element_targets;
+extern const char * const config_element_target_pid;
extern const char * const config_domain_type_kernel;
extern const char * const config_domain_type_ust;
const char * const config_element_shared_memory_path = "shared_memory_path";
const char * const config_element_pid_tracker = "pid_tracker";
const char * const config_element_trackers = "trackers";
+const char * const config_element_targets = "targets";
+const char * const config_element_target_pid = "pid_target";
const char * const config_domain_type_kernel = "KERNEL";
const char * const config_domain_type_ust = "UST";
return ret;
}
+static
+int process_pid_tracker_node(xmlNodePtr pid_tracker_node,
+ struct lttng_handle *handle)
+{
+ int ret, child;
+ xmlNodePtr targets_node = NULL;
+ xmlNodePtr node;
+
+ assert(handle);
+ assert(pid_tracker_node);
+ /* get the targets node */
+ for (node = xmlFirstElementChild(pid_tracker_node); node;
+ node = xmlNextElementSibling(node)) {
+ if (!strcmp((const char *) node->name,
+ config_element_targets)) {
+ targets_node = node;
+ break;
+ }
+ }
+
+ if (!targets_node) {
+ ret = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /* Go through all pid_target node */
+ child = xmlChildElementCount(targets_node);
+ if (child == 0) {
+ /* The session is explicitly set to target nothing. */
+ ret = lttng_untrack_pid(handle, -1);
+ if (ret) {
+ goto end;
+ }
+ }
+ for (node = xmlFirstElementChild(targets_node); node;
+ node = xmlNextElementSibling(node)) {
+ xmlNodePtr pid_target_node = node;
+
+ /* get pid node and track it */
+ for (node = xmlFirstElementChild(pid_target_node); node;
+ node = xmlNextElementSibling(node)) {
+ if (!strcmp((const char *) node->name,
+ config_element_pid)) {
+ int64_t pid;
+ xmlChar *content = NULL;
+
+ content = xmlNodeGetContent(node);
+ if (!content) {
+ ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
+ goto end;
+ }
+
+ ret = parse_int(content, &pid);
+ free(content);
+ if (ret) {
+ ret = LTTNG_ERR_LOAD_INVALID_CONFIG;
+ goto end;
+ }
+
+ ret = lttng_track_pid(handle, (int) pid);
+ if (ret) {
+ goto end;
+ }
+ }
+ }
+ node = pid_target_node;
+ }
+
+end:
+ return ret;
+}
+
+
static
int process_domain_node(xmlNodePtr domain_node, const char *session_name)
{
struct lttng_domain domain = { 0 };
struct lttng_handle *handle = NULL;
xmlNodePtr channels_node = NULL;
+ xmlNodePtr trackers_node = NULL;
+ xmlNodePtr pid_tracker_node = NULL;
xmlNodePtr node;
assert(session_name);
goto end;
}
}
+
+ /* get the trackers node */
+ for (node = xmlFirstElementChild(domain_node); node;
+ node = xmlNextElementSibling(node)) {
+ if (!strcmp((const char *) node->name,
+ config_element_trackers)) {
+ trackers_node = node;
+ break;
+ }
+ }
+
+ if (!trackers_node) {
+ goto end;
+ }
+
+ for (node = xmlFirstElementChild(trackers_node); node;
+ node = xmlNextElementSibling(node)) {
+ if (!strcmp((const char *)node->name,config_element_pid_tracker)) {
+ pid_tracker_node = node;
+ ret = process_pid_tracker_node(pid_tracker_node, handle);
+ if (ret) {
+ goto end;
+ }
+ }
+ }
+
+ if (!pid_tracker_node) {
+ lttng_track_pid(handle, -1);
+ }
+
end:
lttng_destroy_handle(handle);
return ret;
THE SOFTWARE.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
-elementFormDefault="qualified" version="2.5">
+elementFormDefault="qualified" version="2.7">
<xs:simpleType name="name_type">
<xs:restriction base="xs:string">
<xs:complexType name="channel_list_type">
<xs:sequence>
- <xs:element name="channel" type="channel_type" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="channel" type="channel_type" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
-<!-- Maps to struct lttng_domain and contains channels -->
+<xs:complexType name="pid_target_type">
+ <xs:all>
+ <xs:element name="pid" type="xs:integer" />
+ </xs:all>
+</xs:complexType>
+
+<!-- Maps to a list of pid_targets-->
+<xs:complexType name="targets_type">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="pid_target" type="pid_target_type" minOccurs="0" maxOccurs="unbounded" />
+ </xs:choice>
+ </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to a pid_tracker-->
+<xs:complexType name="pid_tracker_type">
+ <xs:all>
+ <xs:element name="targets" type="targets_type" />
+ </xs:all>
+</xs:complexType>
+
+<!-- Maps to a list of trackers-->
+<xs:complexType name="trackers_type">
+ <xs:sequence minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="pid_tracker" type="pid_tracker_type" maxOccurs="1" />
+ </xs:sequence>
+</xs:complexType>
+
+<!-- Maps to struct lttng_domain, contains channels and pid_tracker -->
<xs:complexType name="domain_type">
<xs:all>
<xs:element name="type" type="domain_type_type"/>
<xs:element name="buffer_type" type="domain_buffer_type"/>
<xs:element name="channels" type="channel_list_type" minOccurs="0"/>
+ <xs:element name="trackers" type="trackers_type" minOccurs="0"/>
</xs:all>
</xs:complexType>