2 * Copyright (C) 2013 - Julien Desfossez <jdesfossez@efficios.com>
3 * David Goulet <dgoulet@efficios.com>
4 * 2015 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License, version 2 only, as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 51
17 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <common/common.h>
22 #include <urcu/rculist.h>
24 #include "lttng-relayd.h"
25 #include "ctf-trace.h"
27 #include "viewer-session.h"
28 #include "viewer-stream.h"
31 struct relay_viewer_session
*viewer_session_create(void)
33 struct relay_viewer_session
*vsession
;
35 vsession
= zmalloc(sizeof(*vsession
));
39 CDS_INIT_LIST_HEAD(&vsession
->session_list
);
44 /* The existence of session must be guaranteed by the caller. */
45 int viewer_session_attach(struct relay_viewer_session
*vsession
,
46 struct relay_session
*session
)
50 ASSERT_LOCKED(session
->lock
);
52 /* Will not fail, as per the ownership guarantee. */
53 if (!session_get(session
)) {
57 if (session
->viewer_attached
) {
60 session
->viewer_attached
= true;
64 pthread_mutex_lock(&vsession
->session_list_lock
);
65 /* Ownership is transfered to the list. */
66 cds_list_add_rcu(&session
->viewer_session_node
,
67 &vsession
->session_list
);
68 pthread_mutex_unlock(&vsession
->session_list_lock
);
70 /* Put our local ref. */
77 /* The existence of session must be guaranteed by the caller. */
78 static int viewer_session_detach(struct relay_viewer_session
*vsession
,
79 struct relay_session
*session
)
83 pthread_mutex_lock(&session
->lock
);
84 if (!session
->viewer_attached
) {
87 session
->viewer_attached
= false;
91 pthread_mutex_lock(&vsession
->session_list_lock
);
92 cds_list_del_rcu(&session
->viewer_session_node
);
93 pthread_mutex_unlock(&vsession
->session_list_lock
);
94 /* Release reference held by the list. */
97 /* Safe since we know the session exists. */
98 pthread_mutex_unlock(&session
->lock
);
102 void viewer_session_destroy(struct relay_viewer_session
*vsession
)
104 lttng_trace_chunk_put(vsession
->current_trace_chunk
);
109 * Release ownership of all the streams of one session and detach the viewer.
111 void viewer_session_close_one_session(struct relay_viewer_session
*vsession
,
112 struct relay_session
*session
)
114 struct lttng_ht_iter iter
;
115 struct relay_viewer_stream
*vstream
;
118 * TODO: improvement: create more efficient list of
119 * vstream per session.
121 cds_lfht_for_each_entry(viewer_streams_ht
->ht
, &iter
.iter
,
122 vstream
, stream_n
.node
) {
123 if (!viewer_stream_get(vstream
)) {
126 if (vstream
->stream
->trace
->session
!= session
) {
127 viewer_stream_put(vstream
);
130 /* Put local reference. */
131 viewer_stream_put(vstream
);
133 * We have reached one of the viewer stream's lifetime
134 * end condition. This "put" will cause the proper
135 * teardown of the viewer stream.
137 viewer_stream_put(vstream
);
140 viewer_session_detach(vsession
, session
);
143 void viewer_session_close(struct relay_viewer_session
*vsession
)
145 struct relay_session
*session
;
148 cds_list_for_each_entry_rcu(session
,
149 &vsession
->session_list
, viewer_session_node
) {
150 viewer_session_close_one_session(vsession
, session
);
156 * Check if a connection is attached to a session.
157 * Return 1 if attached, 0 if not attached, a negative value on error.
159 int viewer_session_is_attached(struct relay_viewer_session
*vsession
,
160 struct relay_session
*session
)
162 struct relay_session
*iter
;
165 pthread_mutex_lock(&session
->lock
);
169 if (!session
->viewer_attached
) {
173 cds_list_for_each_entry_rcu(iter
,
174 &vsession
->session_list
,
175 viewer_session_node
) {
176 if (session
== iter
) {
184 pthread_mutex_unlock(&session
->lock
);
188 int viewer_session_set_trace_chunk(struct relay_viewer_session
*vsession
,
189 struct lttng_trace_chunk
*relay_session_trace_chunk
)
192 struct lttng_trace_chunk
*viewer_chunk
;
194 assert(relay_session_trace_chunk
);
195 assert(!vsession
->current_trace_chunk
);
197 DBG("Copying relay session's current trace chunk to the viewer session");
198 viewer_chunk
= lttng_trace_chunk_copy(relay_session_trace_chunk
);
200 ERR("Failed to create a viewer trace chunk from the relay session's current chunk");
205 vsession
->current_trace_chunk
= viewer_chunk
;